web-dev-qa-db-fra.com

Qu'est-ce qui cause l'erreur de tuyau cassé?

Je sais qu'une erreur de canal cassé est renvoyée lorsque le socket côté homologue est fermé.

Mais, lors de mon test, j'ai constaté qu'un appel immédiat à l'envoi de ce côté lorsque le côté homologue est fermé ne conduit pas toujours à une erreur de canal cassé.

Par exemple.:

Après avoir fermé le socket côté homologue (j’ai essayé de fermer proprement en appelant close et également de fermer anormalement en tuant le pair), si j’essaie d’envoyer 40 octets, je n’obtiens pas un tuyau cassé, mais si j’essaie de envoi 40000 octets alors il donne immédiatement une erreur de canal cassé.

Qu'est-ce qui cause exactement un tuyau cassé et son comportement peut-il être prédit?

70
Jay

L’observation de la fermeture du réseau peut prendre un certain temps - le temps total est nominalement d’environ 2 minutes (oui, minutes!) Après la fermeture, avant que les paquets destinés au port ne soient tous supposés morts. La condition d'erreur est détectée à un moment donné. Avec une petite écriture, vous vous trouvez dans la MTU du système. Le message est donc mis en file d'attente pour l'envoi. Avec une écriture importante, vous êtes plus gros que le MTU et le système détecte le problème plus rapidement. Si vous ignorez le signal SIGPIPE, les fonctions renverront l'erreur EPIPE sur un tuyau rompu - à un moment donné lorsque la rupture de la connexion est détectée.

47
Jonathan Leffler

L'état actuel d'un socket est déterminé par l'activité 'Keep-alive'. Dans votre cas, il est possible que lorsque vous émettez l'appel send, le keep-alive activity indique que le socket est actif et donc l'appel send écrit les données requises (40 octets) dans la mémoire tampon et retourne sans donner d'erreur.

Lorsque vous envoyez un plus gros morceau, l'appel envoyé passe en état de blocage.

La page de manuel d'envoi confirme également ceci:

Lorsque le message ne rentre pas dans le tampon d'envoi de la socket, send () bloque normalement, à moins que la socket n'ait été placée en mode E/S non bloquant. En mode non bloquant, il renverrait EAGAIN dans ce cas.

Ainsi, tout en bloquant le tampon disponible libre, si l'appelant est averti (par le mécanisme de maintien de la vie) que l'autre extrémité n'est plus présente, l'appel envoyé échouera.

Il est difficile de prédire le scénario exact avec les informations mentionnées, mais je pense que cela devrait être la raison de votre problème.

8
Vikram.exe

Peut-être que les 40 octets s’intègrent dans le tampon de canal et pas les 40000 octets?

Modifier:

Un signal SIGPIPE est envoyé au processus d’envoi lorsque vous essayez d’écrire dans un canal fermé. Je ne sais pas exactement quand le signal est envoyé ni quel est l'effet du tampon de canal sur cela. Vous pourrez peut-être récupérer en interceptant le signal avec l'appel de sigaction.

3
Joel

Lorsque les homologues se ferment, vous ne savez tout simplement pas s’il arrête d’envoyer ou les envois et les envois à la fois.Parce TCP permet cela, au fait, vous devriez connaître la différence entre fermer et arrêter. Si les deux homologues s’arrêtent Envoi et réception, tout d'abord, vous envoyez des octets, mais le noyau homologue vous enverra la taxe RST. Par la suite, vous enverrez des octets, votre noyau vous enverra un signal SIGPIPE, si vous attrapez ou ignorez ce signal, lorsque votre envoi est renvoyé. , vous obtenez juste une erreur de canal cassé, ou si vous ne le faites pas, le comportement par défaut de votre programme se bloque.

0
kingkong