2009-10-02 24 views
14

Quiero verificar el estado de la conexión antes de realizar mis operaciones (lectura/escritura).boost :: asio :: ip :: tcp :: socket está conectado?

¿Hay alguna manera de hacer un método isConnect()?

vi this, pero parece "feo".

I probado is_open() función también, pero no tiene el comportamiento esperado.

+0

posible duplicado de [¿Cómo comprobar si el socket está cerrado en Boost.Asio?] (Http://stackoverflow.com/questions/818665/how-to-check-if-socket-is-closed-in-boost -asio) – joshperry

Respuesta

28

TCP está destinado a ser robusta frente a una red dura; a pesar de que TCP proporciona lo que parece una conexión persistente de extremo a extremo, todo es solo una mentira, cada paquete es realmente solo un datagrama único y poco confiable.

Las conexiones son realmente conductos virtuales creados simplemente con un poco de estado actualizado en cada extremo de la conexión (puertos y direcciones de origen y de destino, y el zócalo local). La pila de red usa este estado para saber a qué proceso dar cada paquete entrante y qué estado colocar en el encabezado de cada paquete saliente.

Virtual TCP Conduit

Debido a la subyacente — inherentemente conexión y no fiable — naturaleza de la red, la pila sólo informará una conexión cortada cuando el extremo remoto envía un paquete FIN para cerrar la conexión, o si doesn' t recibir una respuesta ACK a un paquete enviado (después de un tiempo de espera y un par de reintentos).

Debido a la naturaleza asíncrona de asio, la manera más fácil de recibir una desconexión elegante es tener un async_read sobresaliente que devolverá error::eof inmediatamente cuando se cierre la conexión. Pero esto solo deja la posibilidad de que otros problemas como conexiones semiabiertas y problemas de red no se detecten.

La manera más efectiva manera de evitar la interrupción inesperada conexión es utilizar algún tipo de mantenimiento de conexión o de ping. Este intento ocasional de transferir datos a través de la conexión permitirá la detección conveniente de una conexión cortada involuntariamente.

El protocolo TCP en realidad tiene incorporado keep-alive mechanism que se puede configurar en asio usando asio::tcp::socket::keep_alive. Lo bueno de TCP keep-alive es que es transparente para la aplicación en modo usuario, y solo los pares interesados ​​en mantener activo deben configurarlo. La desventaja es que necesita acceso/conocimiento de nivel de sistema operativo para configurar los parámetros de tiempo de espera, desafortunadamente no están expuestos a través de una opción de socket simple y generalmente tienen valores de tiempo de espera predeterminados que son bastante grandes (7200 segundos en Linux).

Probablemente el método más común de keep-alive es implementarlo en la capa de aplicación, donde la aplicación tiene un mensaje especial de noop o ping y no hace más que responder cuando le hacen cosquillas. Este método le brinda la mayor flexibilidad para implementar una estrategia de mantenerse vivo.

+0

Hay un problema con el enfoque keep-alive: no tengo acceso a los servidores donde se ejecutará la aplicación, por lo tanto, no puedo cambiar el tiempo de espera de mantener vivo (7200 segundos aquí). Pero me gusta esta respuesta, así que si necesito esto de nuevo, habilitaré TCP keel-alive. Gracias – coelhudo

+0

Olvidé decir lo que hice, solo intento leer/escribir, verificar el error y tomar una decisión basada en este error. – coelhudo

+0

La imagen ya no aparece, ¿puedes arreglar esto por favor? Me gustaría ver la ilustración. Gracias. – coelhudo

0

puede enviar un byte ficticio en un socket y ver si se devolverá un error.

+3

Pero, ¿qué ocurre con el otro extremo cuando recibe este byte ficticio si está conectado? Esa no es una buena solución. – jmucchiello

+2

Por lo general, este tipo de aplicación tiene un concepto de latido cardíaco enviado periódicamente. Además, en Windows (win32) no hay forma de verificar la conexión de manera confiable, y boost :: asio :: ip :: tcp :: socket se implementará encima. @jmucchiello: si alguna vez trabajó en un sistema distribuido, sabría que la conexión siempre se verifica mediante un latido, que generalmente es un byte. Espero que esto ayude al OP. – vehomzzz

+0

Hay un problema, no sé el comportamiento en el lado del servidor. La solución que encontré, es conectar antes de las operaciones y verificar la condición de error. – coelhudo

1

TCP promete vigilar los paquetes descartados - volver a intentar en su caso - para darle una conexión fiable, por alguna definición de fiable. Por supuesto, TCP no puede manejar casos en los que el servidor falla, o se cae su cable Ethernet o ocurre algo similar. Además, saber que su conexión TCP está activa no significa necesariamente que esté listo un protocolo que pasará por la conexión TCP (por ejemplo, su servidor web HTTP o su servidor FTP pueden estar en un estado defectuoso).

Si conoce el protocolo que se envían a través de TCP entonces probablemente hay una manera en la que el protocolo que le diga si las cosas están en buena forma (para HTTP que sería una HEAD request)

Cuestiones relacionadas