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