2009-02-17 16 views
0

J'expérimente des winsockets C++. Je veux créer une méthode avec laquelle je peux trouver le serveur sur le réseau, sans savoir que c'est IP. Pour ce faire, je boucle simplement ma méthode connect via les adresses IP 192.168.1.0 à 192.168.1.255. Cependant, le temps entre chaque connexion est assez important, le programme a tendance à attendre le message: connect (nBytes, (sockaddr *) & server, sizeof (server)) pendant au moins 30 secondes si ce n'est plus. Mes questions sont les suivantes: Pourquoi cela se passe-t-il, comment puis-je résoudre cela et pourrait-il y avoir une façon entièrement différente et meilleure de trouver le serveur?Comment faire un scan réseau-ip en C++?

ma méthode de connexion:

SOCKET connect(char *ipAdress) 
{ 
WSAData wsaData; 

if ((WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR) 
    return errorReport("Could not create startup struct"); 

nBytes = socket(AF_INET, SOCK_STREAM, 0); 

if (nBytes == SOCKET_ERROR) 
    return errorReport("Socket could not be created"); 

struct hostent *host_entry; 

if ((host_entry = gethostbyname(ipAdress)) == NULL) 
    return errorReport("Cannot find server."); 

struct sockaddr_in server; 
server.sin_family = AF_INET; 
server.sin_port = htons(1337); 
server.sin_addr.s_addr = *(unsigned long*) host_entry->h_addr; 

if (connect(nBytes, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) 
{ 
    WSACleanup(); 
    return errorReport("Failed to connect to server."); 
} 

if (nBytes == -1) 
{ 
    WSACleanup(); 
    disconnect(nBytes); 
    return errorReport("Could not connect"); 
} 

return 0; 
} 

Aussi, ne hésitez pas à me dire tout ce que je fais mal dans la méthode de connexion actuelle.

Répondre

3

Le délai long est dû au fait que le socket doit expirer avant de revenir à l'appelant. Pour réduire le temps d'exécution total, vous devez créer plusieurs threads de travail qui se connectent simultanément à des adresses IP distinctes.

1

Je ferais une recherche pour savoir si winsock supporte les E/S asynchrones.

3

OK, quelques choses ici. Tout d'abord, la connexion est conçue pour attendre un peu avant de s'éteindre au cas où le serveur est occupé. Vous pouvez ajuster la longueur du délai d'attente, même si je ne me souviens pas exactement comment le faire du haut de ma tête. Deuxièmement, votre code va trouver un serveur, mais comment savez-vous que c'est le serveur que vous recherchez? Il pourrait s'agir d'une autre application qui écoute simplement sur le même port. À moins que vous n'effectuiez une analyse pour un serveur en particulier, vous devrez effectuer une vérification pour vous assurer de la personne à qui vous parlez à l'autre extrémité. Enfin, en supposant que vous écrivez à la fois le client et le serveur, une meilleure solution serait que le client envoie un message de diffusion/multidiffusion et que le serveur (ou les serveurs s'il y en a plus d'un) écoute et répondre à ce message. Le client attend alors juste une période de temps spécifiée pour les réponses pour déterminer où sont les serveurs.

1

L'adresse IP du serveur est-elle si aléatoire que vous devez le faire à chaque fois? Je n'ai pas fait de programmation de socket depuis longtemps, mais avec des timeouts et autres, cela pourrait ne pas aller beaucoup mieux.

Autres options:

  • Que diriez-vous d'un fichier de configuration sur un partage réseau avec l'adresse IP? Cela pourrait être réécrit à chaque démarrage du serveur.
  • faire Recherch par DNS ou le nom NETBIOS de la machine
0

l'adresse IP du serveur statique et dur code ou mettre dans un fichier de configuration

  • Si vous connaissez le serveur est sur le sous-réseau, pourquoi pas envoyer un message de diffusion avec le numéro de port de réception locale en tant que données de message? Ensuite, le serveur peut simplement écouter ce message et se reconnecter à ce port, ou renvoyer ses propres données de configuration à ce port afin que le client puisse se connecter directement. De cette façon, vous n'avez qu'à envoyer un message au lieu de boucler plus de 256 adresses IP.

  • 0

    Je l'ai fait par le passé avec beaucoup de succès dans les journées portes ouvertes «tout le monde a le port 139».

    J'ai trouvé que l'utilisation de plusieurs threads (Malheureusement, j'ai utilisé environ 500, mais c'était une seule fois et juste pour le plaisir) et j'ai cinglé le serveur avant de tenter une connexion m'a permis de traverser plusieurs IPs par seconde .

    J'ai toujours le code source (C++) si vous voulez le vérifier, laissez moi un message.

    Aussi, pourquoi diable serait-il jamais nécessaire de scanner les adresses IP? Même si sa dynamique, vous devriez être capable de regarder ip up par son nom d'hôte. Voir gethostbyname() ou getaddrinfo().

    +0

    Bien sûr, j'aimerais y jeter un coup d'œil! Merci! – user23163

    +0

    Je l'ai téléchargé, je vais y jeter un coup d'oeil, merci encore! – user23163

    0

    Je vois que vous utilisez Windows. Mais si vous utilisez Linux, vous pouvez créer une fonction de connexion qui a un délai d'expiration en combinant des sockets non bloquantes et sélectionnez:

    int connect_with_timeout(int sock, struct sockaddr *addr, int size_addr, int timeout) { 
    #if defined(Linux) 
        int    error = 0; 
        fd_set   rset; 
        fd_set   wset; 
        int    n; 
    
        // set the socket as nonblocking IO 
        int flags = fcntl (sock, F_GETFL, 0); 
        fcntl(sock, F_SETFL, flags | O_NONBLOCK); 
    
        errno = 0; 
    
        // we connect, but it will return soon 
        n = connect(sock, addr, size_addr); 
    
        if(n < 0) { 
         if (errno != EINPROGRESS) { 
          return -1; 
         } 
        } else if (n == 0) { 
         goto done; 
        } 
    
        FD_ZERO(&rset); 
        FD_ZERO(&wset); 
        FD_SET(sock, &rset); 
        FD_SET(sock, &wset); 
    
        struct timeval tval; 
        tval.tv_sec = timeout; 
        tval.tv_usec = 0; 
    
        // We "select()" until connect() returns its result or timeout 
        n = select(sock + 1, &rset, &wset, 0, timeout ? &tval : 0); 
        if(n == 0) {  
         errno = ETIMEDOUT; 
         return -1; 
        } 
    
        if (FD_ISSET(sock, &rset) || FD_ISSET(sock, &wset)) { 
         socklen_t len = sizeof(error); 
         if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 
          return -1; 
         } 
        } else { 
         return -1; 
        } 
    
    done: 
        // We change the socket options back to blocking IO 
        if (fcntl(sock, F_SETFL, flags) == -1) { 
         return -1; 
        } 
        return 0; 
    #else 
        return connect(sock, addr, size_addr); 
    #endif 
    } 
    
    Questions connexes