À l'aide de select() pour les sockets non bloquant pour se connecter retourne toujours 1
Cette question est très similaire (ou presque identique) à Non blocage socket de connexion, sélectionnez() retourne toujours 1; cependant, je n'arrive pas à trouver où mon code est en perte de vitesse.
Je suis en utilisant les sockets non bloquant et que vous voulez utiliser select() lors de la connexion d'un client à un serveur pour vérifier timeout/succès. Le problème est de sélectionner() retourne toujours 1 presque immédiatement, même quand je n'ai même pas le serveur en cours d'exécution et il n'y a rien à se connecter. Merci d'avance pour l'aide, extrait de code est comme suit:
//Loop through the addrinfo structs and try to connect to the first one we can
for(p = serverinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
//We couldn't create the socket, try again
perror("client: socket");
continue;
}
//Set the socket to non-blocking
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
//The error was something other than non-block/in progress, try next addrinfo
if(errno != EINPROGRESS)
{
close(sockfd);
perror("client: connect");
continue;
}
fd_set write_fds;
FD_ZERO(&write_fds); //Zero out the file descriptor set
FD_SET(sockfd, &write_fds); //Set the current socket file descriptor into the set
//We are going to use select to wait for the socket to connect
struct timeval tv; //Time value struct declaration
tv.tv_sec = 5; //The second portion of the struct
tv.tv_usec = 0; //The microsecond portion of the struct
//DEBUG: This is ALWAYS 1
int select_ret = select(sockfd + 1, NULL, &write_fds, NULL, &tv);
cout << select_ret << endl;
//Check return, -1 is error, 0 is timeout
if(select_ret == -1 || select_ret == 0)
{
//We had an error connecting
cout << "Error Connecting\n";
close(sockfd);
continue;
}
}
//We successfully connected, break out of loop
break;
}
Thos est presque une copie de stackoverflow.com/questions/8417821/...
OriginalL'auteur Darren Swanson | 2012-07-01
Vous devez vous connecter pour publier un commentaire.
Que faites-vous attendre select() pour revenir? Considérer que select() est normalement utilisé pour attendre plusieurs descripteurs de fichier - si vous étiez connexion deux, comment savoir à qui on a réussi/échoué purement basée sur la valeur de retour de sélection? Vous ne voudriez pas, évidemment.
C'est pourquoi select() vous informe sur les descripteurs de fichiers ont changé, et vous êtes censé déterminer indépendamment de ce que c'était. Dans le cas de connect(), vous devriez appeler getsockopt() pour récupérer le résultat de la tentative de connexion. Voir cette réponse où j'explique comment faire un non-blocage de la fonction connect().
EJP j'ai vu dans la documentation qui explique comment le faire de la manière Ambroz décrit, est la meilleure approche?
Je suis curieux de savoir quels sont les documents dont vous parlez. La méthode officielle dans le Linux connect(2) page de man est à getsockopt(fd, SOL_SOCKET, SO_ERROR, ...) qui, je le sais parce que j'ai écrit la partie de la page de man. Longtemps, j'ai écrit un programme à l'aide de la "connexion-nouveau" la méthode. Il a travaillé pour moi, mais pas pour les utilisateurs BSD, qui a insisté pour que la deuxième se connecter a un stupide Linux de chose.
Notre production SW utilise avec getsockopt (SOL_SOCKET, SO_ERROR) lorsque le support se tourne vers l'écriture. Et il fonctionne bien. Peut-être EJP ont une autre façon de travailler. Mais cette réponse est correcte.
sélectionnez() retourne le nombre de sockets sur le retour. Il n'est pas toujours de retour 1. Ceci ne répond pas à la question.
OriginalL'auteur Ambroz Bizjak
Lors de la connexion en mode sans blocage et sélectionnez() indique que la connexion est accessible en écriture, vous êtes donc censé appel à connect() de nouveau. Faire sera de retour -1 avec errno == ECONNRESET ou quoi que ce soit.
Stevens et Wright, TCP/IP Illustré; Stevens, Unix, Programmation Réseau;* et Douglas Comer TCP livre dont le nom misremember.
Désolé, devrait probablement avoir commenté cette réponse plutôt que celui ci-dessus. Je suis confronté à un problème similaire et compris que j'ai probablement besoin d'appeler connect() de nouveau, mais tous à la recherche, d'autres que ce post, n'est-ce pas de l'indiquer. Aussi, les docs pour se connecter ne pas le mentionner. En fait ECONNRESET n'est même pas répertorié comme une possible erreur de connect(). J'ai cependant de ne voir EISCONN.
OriginalL'auteur user207421