Ответ 1
TCP должен быть надежным перед жесткой сетью; даже несмотря на то, что TCP обеспечивает то, что выглядит как постоянное сквозное соединение, все это просто ложь, каждый пакет - действительно просто уникальная ненадежная датаграмма.
Соединения - это действительно просто виртуальные кабели, созданные с небольшим состоянием, отслеживаемым на каждом конце соединения (исходные и целевые порты и адреса и локальный сокет). Сетевой стек использует это состояние, чтобы узнать, какой процесс должен предоставлять каждый входящий пакет и какое состояние помещать в заголовок каждого исходящего пакета.
Из-за базового — по своей сути бесконтактный и ненадежный; характер сети, стек будет сообщать только о отключенном соединении, когда удаленный конец отправляет FIN-пакет для закрытия соединения или если он не получает ответ ACK на отправленный пакет (после таймаута и повторной попытки пары).
Из-за асинхронного характера asio самый простой способ получить извещение об изящном отключении - иметь выдающийся async_read
, который вернет error::eof
сразу же после закрытия соединения. Но это одно по-прежнему оставляет возможность других неполадок, таких как полуоткрытые соединения и проблемы с сетью, которые остаются незамеченными.
Самый эффективный способ обхода неожиданного прерывания соединения - использовать какой-то режим keep-alive или ping. Эта случайная попытка передачи данных по соединению позволит эффективно обнаруживать непреднамеренно разъединенное соединение.
Протокол TCP фактически имеет встроенный механизм keep-alive, который можно настроить в asio с помощью asio::tcp::socket::keep_alive
. Самое приятное в том, что TCP keep-alive заключается в том, что он прозрачен для приложения с пользовательским режимом, и только его коллеги, заинтересованные в поддержке, должны настроить его. Недостатком является то, что вам нужен доступ/знания уровня ОС для настройки параметров тайм-аута, они, к сожалению, не подвергаются простой опцией сокета, и обычно имеют значения таймаута по умолчанию, которые довольно велики (7200 секунд в Linux).
Вероятно, наиболее распространенным методом keep-alive является его реализация на уровне приложения, где приложение имеет специальное сообщение noop или ping и ничего не реагирует, когда его щекочет. Этот метод дает вам максимальную гибкость при реализации стратегии keep-alive.