2009-10-02 9 views
14

Я хочу проверить состояние соединения, прежде чем реализовать свои операции (чтение/запись).boost :: asio :: ip :: tcp :: socket подключен?

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

Я видел this, но кажется «уродливым».

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

+0

Возможный дубликат [Как проверить, закрыт ли сокет в Boost.Asio?] (Http://stackoverflow.com/questions/818665/how-to-check-if-socket-is-closed-in-boost -asio) – joshperry

ответ

28

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

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

Virtual TCP Conduit

В связи с лежащим в основе — по своей сути установления соединения и ненадежного — характера сети, стек будет сообщать только отрезанное соединение, когда удаленный конец посылает 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.

+0

Существует одна проблема с keep-alive aproach: у меня нет доступа к серверам, на которых будет запущено приложение, поэтому я не могу изменить тайм-аут keep-alive (7200 секунд здесь). Но мне нравится этот ответ, поэтому, если мне это нужно, я включу TCP keel-alive. Спасибо – coelhudo

+0

Я забыл сказать, что я сделал, просто попробую прочитать/написать, проверить ошибку и принять решение на основе этой ошибки. – coelhudo

+0

Изображение больше не отображается, можете ли вы исправить это, пожалуйста? Я хотел бы увидеть иллюстрацию. Благодарю. – coelhudo

0

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

+3

Но что происходит с другим концом, когда он получает этот фиктивный байт, если вы подключены. Это нехорошее решение. – jmucchiello

+2

Обычно такого рода приложения имеют понятие биения пульса периодически. Более того, на windows (win32) нет возможности проверить соединение надежно, а boost :: asio :: ip :: tcp :: socket будет реализован поверх него. @jmucchiello - если вы когда-либо работали в распределенных системах, вы бы знали, что соединение всегда проверяется с помощью биения, которое обычно является байтом. Надеюсь, это поможет OP. – vehomzzz

+0

Есть одна проблема, я не знаю поведения на стороне сервера. Решение, которое я нашел, - это соединение вызова перед операциями и проверка состояния ошибки. – coelhudo

1

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

Если вы знаете, протокол, передаваемых по протоколу TCP, то есть, вероятно, путь в этом протоколе, чтобы сказать вам, если что-то в хорошей форме (для HTTP это будет HEAD request)