2009-10-02 7 views
14

Je souhaite vérifier l'état de la connexion avant de réaliser mes opérations (lecture/écriture).boost :: asio :: ip :: tcp :: le socket est connecté?

Existe-t-il un moyen de créer une méthode isConnect()? J'ai vu this, mais il semble "laid". J'ai également testé is_open() fonction, mais n'a pas le comportement attendu.

+0

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

Répondre

28

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.

Virtual TCP Conduit

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.

+0

Il y a un problème avec keep-alive approche: Je n'ai pas accès aux serveurs où l'application va s'exécuter, donc je ne peux pas changer le timeout keep-alive (7200 secondes ici). Mais j'aime cette réponse, donc si j'en ai encore besoin, je vais activer TCP keel-alive. Merci – coelhudo

+0

J'ai oublié de dire ce que j'ai fait, j'essaie juste de lire/écrire, vérifier l'erreur et prendre une décision basée sur cette erreur. – coelhudo

+0

L'image ne s'affiche plus, pouvez-vous résoudre ce problème s'il vous plaît? J'aimerais voir l'illustration. Merci. – coelhudo

0

Vous pouvez envoyer un octet fictif sur une socket et voir si elle renverra une erreur.

+3

Mais que se passe-t-il à l'autre extrémité quand il reçoit cet octet factice si vous êtes connecté. Ce n'est pas une bonne solution. – jmucchiello

+2

Habituellement ce type d'application a un concept de battement de coeur envoyé périodiquement. De plus, sur windows (win32) n'a pas un moyen de vérifier la connexion de manière fiable, et boost :: asio :: ip :: tcp :: socket serait implémenté par-dessus. @jmucchiello - Si vous avez déjà travaillé sur un système distribué, vous auriez su que la connexion est toujours vérifiée via un battement de cœur, qui est généralement un octet. J'espère que cela aide le PO. – vehomzzz

+0

Il y a un problème, je ne connais pas le comportement du côté serveur. La solution que j'ai trouvée, est de se connecter avant les opérations et de vérifier les conditions d'erreur. – coelhudo

1

TCP promet de surveiller les paquets abandonnés - en réessayant le cas échéant - pour vous donner une connexion fiable, pour une certaine définition de fiable. Bien sûr, TCP ne peut pas gérer les cas où le serveur tombe en panne, ou si votre câble Ethernet tombe en panne ou quelque chose de similaire se produit. De plus, sachant que votre connexion TCP est en haut ne signifie pas nécessairement qu'un protocole qui ira sur la connexion TCP est prêt (par exemple, votre serveur HTTP ou votre serveur FTP peut être dans un état cassé).

Si vous connaissez le protocole envoyé sur TCP alors il y a probablement une façon dans ce protocole de vous dire si les choses sont en bonne forme (pour HTTP il serait HEAD request)

Questions connexes