Dans les parties de communication TCP, pour faciliter la description, les parties de communication sont remplacées par A et B ci-dessous.
Selon le protocole TCP, si B continue d'envoyer des données après que A ait fermé la connexion, B recevra la réponse RST de A. Si B continue d'envoyer des données, le système enverra un signal SIGPIPE pour informer que la connexion a été déconnectée et arrêtera l'envoi.
Le comportement de traitement par défaut du système pour le signal SIGPIPE est de laisser le processus B se terminer.
Le comportement de traitement par défaut du système d'exploitation pour le signal SIGPIPE est très hostile, analysons-le.
La communication TCP est un canal full-duplex, ce qui équivaut à deux canaux simplex, et chaque extrémité de la connexion en est responsable.
Lorsque le homologue "ferme", bien que l'intention soit de fermer les deux canaux dans leur intégralité, l'extrémité locale ne reçoit que le paquet FIN.
Selon les dispositions du protocole TCP, lorsqu'une extrémité ferme le canal unidirectionnel dont elle est responsable, elle peut toujours recevoir des données mais ne plus en envoyer.
En d'autres termes, en raison des limitations du protocole TCP, la partie communicante ne peut pas savoir si le socket du homologue a appelé close ou shutdown.
int shutdown(int socket, int how);
Le paramètre "comment" de la fonction d'arrêt peut être réglé pour fermer SHUT_RD, SHUT_WR ou SHUT_RDWR, qui est utilisé pour indiquer la fermeture des canaux de réception et d'envoi individuellement ou la fermeture des canaux d'envoi et de réception en même temps.
Appelez la méthode read/recv sur un socket qui a reçu un paquet FIN Si le tampon de réception est vide, 0 sera renvoyé, ce qui est souvent considéré comme indiquant que la connexion est fermée. Cependant, lorsque la méthode d'écriture/envoi est appelée pour la première fois, s'il n'y a pas de problème avec le tampon d'envoi, une écriture correcte sera renvoyée (c'est-à-dire que la valeur de retour de la fonction d'écriture/envoi est supérieure à 0) , mais le message envoyé amènera l'homologue à répondre avec un message RST. Parce que la dernière fois que le programme a appelé write/send, c'était normal. Lors d'une nouvelle tentative d'appel de la fonction write/send, le signal SIGPIPE a été généré, provoquant la sortie du processus.
Ce comportement par défaut nous permet de développer des programmes, en particulier pour les services back-end, qui doivent servir plusieurs clients en même temps. L'ensemble du processus ne peut pas se terminer et ne peut pas continuer à servir d'autres clients car il y a un problème de connexion. un certain client.
Afin d'éviter ce phénomène, vous pouvez capter le signal SIGPIPE et le traiter ou ignorer le signal. Le code pour ignorer le signal est le suivant :
signal(SIGPIPE, SIG_IGN);
Après un réglage comme celui-ci, lorsque la méthode write/send est appelée pour la deuxième fois, -1 sera renvoyé et le code d'erreur errno sera défini sur SIGPIPE, afin que le programme sache que le homologue a été fermé.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!