TCP предназначается, чтобы быть надежным перед лицом суровой сети; даже несмотря на то, что TCP обеспечивает то, что выглядит как постоянное сквозное соединение, все это просто ложь, каждый пакет действительно просто уникальная, ненадежная датаграмма.
Соединения - это действительно просто виртуальные кабели, созданные с небольшим состоянием, отслеживаемым на каждом конце соединения (исходные и целевые порты и адреса и локальный сокет). Сетевой стек использует это состояние, чтобы узнать, какой процесс должен дать каждому входящему пакету и какое состояние помещать в заголовок каждого исходящего пакета.
В связи с лежащим в основе — по своей сути установления соединения и ненадежного — характера сети, стек будет сообщать только отрезанное соединение, когда удаленный конец посылает FIN пакет, чтобы закрыть соединение, или если он Безразлично» t получает ответ ACK на отправленный пакет (после тайм-аута и повторной попытки пары).
Из-за асинхронного характера asio самый простой способ получить извещение об изящном отключении - иметь выдающийся async_read
, который немедленно вернет error::eof
, когда соединение будет закрыто. Но это само по себе все еще оставляет возможность других неполадок, таких как полуоткрытые соединения и проблемы с сетью.
Самый эффективный способ обхода неожиданного прерывания соединения - использовать какой-то режим keep-alive или ping. Эта случайная попытка передачи данных по соединению позволит эффективно обнаруживать непреднамеренно разъединенное соединение.
Протокол TCP фактически имеет встроенный keep-alive mechanism, который можно настроить в asio с помощью asio::tcp::socket::keep_alive
. Самое приятное в том, что TCP keep-alive заключается в том, что он прозрачен для пользовательского режима, и только его сверстники, заинтересованные в поддержке, должны настроить его. Недостатком является то, что вам нужен доступ/знания уровня ОС для настройки параметров тайм-аута, к сожалению, они не отображаются через простую опцию сокета и обычно имеют значения таймаута по умолчанию, которые довольно велики (7200 секунд в Linux).
Возможно, наиболее распространенным методом keep-alive является его реализация на прикладном уровне, где приложение имеет специальное сообщение noop или ping и ничего не дает, кроме как реагировать на щекотание. Этот метод дает вам максимальную гибкость при реализации стратегии keep-alive.
Возможный дубликат [Как проверить, закрыт ли сокет в Boost.Asio?] (Http://stackoverflow.com/questions/818665/how-to-check-if-socket-is-closed-in-boost -asio) – joshperry