3 votes

<select> dit que le socket est prêt à être lu alors qu'il ne l'est pas du tout (il est en fait déjà fermé)

Sur mon serveur, je vérifie si un socket est prêt à être lu en utilisant select() pour le déterminer. En conséquence, dans la boucle principale, select() est exécuté à chaque itération.

Pour tester le serveur, j'ai écrit un client simple qui envoie un seul message puis se ferme. Au fait, j'utilise des protocoles protobuf pour envoyer des informations - message signifie un objet de type classe Message dans cette bibliothèque.

La session de test ressemble à ceci :

  1. select()
  2. socket du serveur prêt à être lu
  3. accept() le socket du client
  4. lire le message du socket du client
  5. select()
  6. socket du serveur pas prêt à être lu, celui du client prêt
  7. lire le message du socket du client

La dernière étape est incorrecte car le client a déjà fermé la connexion. En conséquence, la bibliothèque protobuf obtient Segmentation fault. Je me demande pourquoi FD_ISSET indique que le socket est prêt à l'étape 6 lorsqu'il est fermé. Comment puis-je vérifier si un socket est fermé ?


ÉDITER :

J'ai trouvé comment vérifier si le socket est ouvert

int error = 0;
socklen_t len = sizeof (error);
int retval = getsockopt (socket_fd, SOL_SOCKET, SO_ERROR, &error, &len );

12voto

Hasturkun Points 18653

La socket est "lisible" si le pair distant la ferme, vous devez appeler recv et gérer les deux cas où il renvoie une erreur, et le cas où il renvoie 0, ce qui indique que le pair a fermé la connexion de manière ordonnée.

Lecture de l'option de socket SO_ERROR n'est pas la bonne façon de faire, car cela renvoie l'erreur en attente actuelle (par ex. d'une connect non bloquante)

1voto

skarnet Points 21

Le socket utilisé pour la communication entre un client et votre serveur sera marqué comme lisible (c.-à-d. select() retournera) lorsqu'il y a des données à lire, ou lorsqu'il y a une fin de fichier à lire (c.-à-d. le pair a fermé la connexion).

Lire simplement avec read() lorsque select() retourne et que votre descripteur de fichier est marqué. Si read() renvoie un nombre positif, vous avez des données. S'il renvoie 0, vous avez atteint la fin de fichier. S'il renvoie -1, vous avez un problème (sauf si errno est EAGAIN).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X