Question

Comment TCP / IP signale-t-il les erreurs en cas d'échec permanent de la livraison de paquets? Toutes les API Socket.write () que j'ai vues se contentent de passer des octets au tampon de sortie TCP / IP sous-jacent et de transférer les données de manière asynchrone. Comment alors TCP / IP est-il censé avertir le développeur si la livraison du paquet échoue de manière permanente (c’est-à-dire que l’hôte de destination n’est plus accessible)?

Tout protocole obligeant l'expéditeur à attendre la confirmation de l'extrémité distante recevra un message d'erreur. Mais que se passe-t-il pour les protocoles où un expéditeur ne doit lire aucun octet de la destination? TCP / IP échoue-t-il simplement en silence? Peut-être que Socket.close () retournera une erreur? La spécification TCP / IP dit-elle quelque chose à ce sujet?

Était-ce utile?

La solution

TCP / IP est un protocole de flux d'octets fiable. Tous vos octets seront envoyés au destinataire ou vous obtiendrez une indication d'erreur.

L'indication d'erreur se présentera sous la forme d'une socket fermée. Indépendamment de ce que le modèle de communication (qui envoie), si les octets ne peuvent pas être livrés, le socket sera fermé.

La question est donc: comment voyez-vous la prise se fermer? Si vous ne lisez jamais, vous obtiendrez éventuellement une erreur en essayant d’écrire dans le socket fermé (avec ECONNRESET errno, je pense).

Si vous avez besoin de dormir ou d’attendre une entrée sur un autre descripteur de fichier, vous pouvez attendre votre appel à un appel à select () en incluant le socket dans la liste des sources en attente (même si vous ne vous attendez jamais à recevoir quoi que ce soit). Si le select () indique que le socket est prêt pour un appel en lecture, vous pouvez obtenir un retour -1 (avec ECONNRESET, je pense). Un EOF indiquerait une fermeture ordonnée (l'autre partie a procédé à un arrêt () ou à une fermeture ().

Comment distinguer cette erreur près d’une fermeture propre (autre programme sortant, par exemple)? Les valeurs errno peuvent suffire à distinguer l’erreur de la fermeture ordonnée.

Si vous souhaitez une indication non ambiguë d'un problème, vous devrez probablement créer un protocole de niveau application au-dessus de la couche de socket. Par exemple, un court "Ack" " message envoyé par le destinataire à l'expéditeur. Ensuite, la violation de ce protocole d’application de niveau supérieur (l’expéditeur n’a pas vu d'accusé de réception) serait une confirmation qu'il s'agissait d'une erreur proche plutôt que propre.

Autres conseils

L’API de socket n’a aucun moyen d’informer le rédacteur du nombre exact d’octets reçus comme reconnus par l’homologue. La présence réussie de shutdown ou de close n'est pas garantie.

La spécification TCP / IP ne dit rien sur l'interface d'application (qui est presque toujours l'API sockets).

SCTP est une alternative au protocole TCP qui tente, entre autres, de remédier à ces problèmes.

En C, si vous écrivez dans un socket qui a échoué avec send (), vous récupérerez le nombre d'octets envoyés. Si cela ne correspond pas au nombre d'octets que vous vouliez envoyer, vous avez un problème. Mais aussi, lorsque vous écrivez sur un socket en échec, vous récupérez SIGPIPE. Avant de commencer la gestion des sockets, vous devez disposer d’un gestionnaire de signal qui vous alertera lorsque vous obtiendrez SIGPIPE.

Si vous lisez une prise, vous devriez vraiment l'envelopper avec une alarme afin que vous puissiez expirer. J'aime " alarm (timeout_val); recv (); alarme (0) ". Vérifiez le code de retour de recv, et si c'est 0, cela indique que la connexion a été fermée. Un résultat négatif indique un échec de lecture et vous devez vérifier errno.

TCP repose sur le protocole IP, pièce maîtresse d’Internet, qui assure une grande partie de l’interopérabilité qui sous-tend le routage, déterminant de la manière dont les paquets doivent être acheminés de leur source à leur destination. Le protocole IP spécifie que les messages d'erreur doivent être renvoyés à l'expéditeur via le protocole ICMP (Internet Control Message Protocol) dans le cas où un paquet ne parvient pas à l'expéditeur. Certaines de ces raisons incluent le fait que le champ TTL (Time To Live) soit décrémenté à zéro, ce qui signifie souvent que le paquet est resté bloqué dans une boucle de routage ou qu'il a été abandonné en raison d'un conflit de commutateur entraînant un dépassement de la mémoire tampon. Comme d'autres l'ont déjà dit, l'API Socket utilisée est chargée de relayer ces erreurs au niveau de la couche IP jusqu'à l'application qui interagit avec le réseau au niveau de la couche TCP.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top