boost::asio::ip::tcp:: сокет подключен?

Я хочу проверить состояние соединения перед выполнением операций чтения / записи.

есть ли способ сделать isConnect() метод?

Я видел этой, но это, кажется, "некрасиво".

Я испытал is_open () функция также, но она не имеет ожидаемого поведения.

3 ответов


TCP должен быть надежным перед лицом жесткой сети; даже если TCP обеспечивает то, что выглядит как постоянное сквозное соединение, это все просто ложь, каждый пакет на самом деле просто уникальная, ненадежная дейтаграмма.

соединения на самом деле просто виртуальные каналы, созданные с небольшим состоянием, отслеживаемым на каждом конце соединения (исходные и целевые порты и адреса и локальный сокет). Сетевой стек использует это состояние, чтобы знать, какой процесс давать каждому входящему пакет В и какое состояние поместить в заголовок каждого исходящего пакета.

Virtual TCP Conduit

из - за базового - по своей сути без подключения и ненадежного-характера сети стек будет сообщать только о разорванном соединении, когда удаленный конец отправляет пакет FIN для закрытия соединения или если он не получает ответ ACK на отправленный пакет (после тайм-аута и нескольких попыток).

из-за асинхронной природы asio, самый простой способ будьте уведомлены о изящном отключении, чтобы иметь выдающийся async_read что вернет error::eof сразу после закрытия соединения. Но это само по себе все еще оставляет возможность других проблем, таких как полуоткрытые соединения и сетевые проблемы, незамеченными.

наиболее эффективный способ обойти неожиданное прерывание соединения-использовать какой-то keep-alive или ping. Эта случайная попытка передачи данных по соединению позволит целесообразное обнаружение нечаянно разорвала связь.

протокол TCP на самом деле имеет встроенный keep-живой механизм который можно настроить в asio с помощью asio::tcp::socket::keep_alive. Хорошая вещь о TCP keep-alive заключается в том, что он прозрачен для приложения пользовательского режима, и только пэры, заинтересованные в keep-alive, должны его настроить. Недостатком является то, что вам нужен доступ/знание уровня ОС для настройки параметров тайм-аута, они, к сожалению, не отображаются с помощью простой опции сокета и обычно имеют значения тайм-аута по умолчанию, которые довольно велики (7200 секунд в Linux).

вероятно, наиболее распространенным методом keep-alive является его реализация на уровне приложения, где приложение имеет специальное сообщение noop или ping и ничего не делает, кроме ответа при щекотке. Этот метод дает вам наибольшую гибкость в реализации стратегии поддержания жизни.


TCP обещает следить за отброшенными пакетами - повторная попытка по мере необходимости - чтобы дать вам надежное соединение, для некоторого определения надежного. Конечно, TCP не может обрабатывать случаи, когда сервер аварийно завершает работу, или ваш кабель Ethernet выпадает или происходит что-то подобное. Кроме того, зная, что ваше TCP-соединение не обязательно означает, что протокол, который будет проходить через TCP-соединение, готов (например., ваш веб-сервер HTTP или ваш FTP-сервер могут быть в некоторых сломанных государство.)

Если вы знаете, что протокол отправляется по TCP, то, вероятно, в этом протоколе есть способ сообщить вам, все ли в порядке (для HTTP это будет запрос Head)


вы можете отправить фиктивный байт в сокет и посмотреть, вернет ли он ошибку.