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.
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.
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