TCP est censé être robuste face à un réseau dur; Même si TCP fournit ce qui ressemble à une connexion de bout en bout persistante, tout est juste un mensonge, chaque paquet est vraiment juste un datagramme unique et non fiable.
Les connexions ne sont en réalité que des conduits virtuels créés avec un petit état suivi à chaque extrémité de la connexion (ports et adresses source et de destination, et socket local). La pile réseau utilise cet état pour savoir quel processus doit donner à chaque paquet entrant et quel état mettre dans l'en-tête de chaque paquet sortant.
En raison du sous-jacent — nature — intrinsèquement connexion et peu fiable du réseau, la pile ne signaler une connexion sectionnée lorsque l'extrémité distante envoie un paquet FIN pour fermer la connexion, ou si elle n » t recevoir une réponse ACK à un paquet envoyé (après un timeout et quelques tentatives). En raison de la nature asynchrone d'asio, le moyen le plus simple d'être averti d'une déconnexion progressive est d'avoir un async_read
exceptionnel qui renverra error::eof
immédiatement lorsque la connexion sera fermée. Mais cela seul laisse encore la possibilité d'autres problèmes comme des connexions à moitié ouvertes et des problèmes de réseau qui ne sont pas détectés.
La manière la plus efficace de contourner une interruption de connexion inattendue consiste à utiliser une sorte de keep-alive ou ping. Cette tentative occasionnelle de transférer des données sur la connexion permettra une détection rapide d'une connexion coupée involontairement.
Le protocole TCP a en fait un keep-alive mechanism intégré qui peut être configuré en asio en utilisant asio::tcp::socket::keep_alive
. La bonne chose à propos de TCP keep-alive est qu'il est transparent pour l'application en mode utilisateur, et seuls les pairs intéressés par keep-alive ont besoin de le configurer. L'inconvénient est que vous avez besoin d'un accès au niveau OS pour configurer les paramètres de timeout, ils ne sont malheureusement pas exposés via une simple option de socket et ont généralement des valeurs de timeout par défaut assez importantes (7200 secondes sous Linux).
Probablement la méthode la plus courante de keep-alive est de l'implémenter au niveau de la couche application, où l'application a un message spécial noop ou ping et ne fait que répondre quand elle est chatouillée. Cette méthode vous donne la plus grande flexibilité dans la mise en œuvre d'une stratégie keep-alive.
duplication possible de [Comment vérifier si socket est fermé dans Boost.Asio?] (Http://stackoverflow.com/questions/818665/how-to-check-if-socket-is-closed-in-boost -asio) – joshperry