2014-01-26 2 views

ответ

18

В обычном случае, когда клиент закрывает сокет через close(), и соединение подтверждения TCP было успешно завершено, произойдет событие channelInactive() (или channelClosed() в 3).

Однако, в необычном случае, когда клиентская машина отключается из-за сбоя питания или отсоединенного сетевого кабеля, это может занять много времени, пока вы не обнаружите, что соединение было фактически отключено. Чтобы обнаружить эту ситуацию, вам нужно периодически отправлять сообщение клиенту и ожидать получения ответа в течение определенного времени. Это похоже на ping - вы должны определить периодическое сообщение ping и pong в своем протоколе, который практически ничего не делает, кроме проверки работоспособности соединения.

В качестве альтернативы вы можете включить SO_KEEPALIVE, но интервал между этими параметрами обычно зависит от ОС, и я бы не рекомендовал его использовать.

Чтобы помочь пользователю реализовать подобное поведение относительно легко, Netty предоставляет ReadTimeoutHandler. Настройте свой конвейер так, чтобы ReadTimeoutHandler вызывал исключение, когда нет входящего трафика в течение определенного времени, и закрывайте соединение с исключением в вашем методе обработчика exceptionCaught(). Если вы являетесь участником, который должен послать периодическое сообщение ping, используйте таймер (или IdleStateHandler), чтобы отправить его.

0

Это зависит от вашего протокола, что вы используете ontop netty. Если вы создадите его для поддержки сообщений, подобных ping, вы можете просто отправить эти сообщения. Кроме того, netty - всего лишь довольно тонкая оболочка вокруг TCP.

Также см. this SO post, который описывает isOpen() и связанные с ним. Однако это не решает проблему сохранения жизни.

+0

Ответы в этой ссылке в основном неверны. В SO есть намного лучшие ответы. – EJP

+0

@EJP У вас есть ссылка? Если бы вы могли предложить редактирование, я с радостью соглашусь с этим! –

+0

Мое понимание заключается в том, что tcp имеет встроенный встроенный модуль. Нельзя ли использовать это? –

0

Если вы пишете сервер, а netty - ваш клиент, то ваш сервер может обнаружить отключение, вызвав select() или эквивалент, чтобы определить, когда сокет читается, а затем позвонить recv(). Если recv() возвращает 0, то сокет был закрыт изящно клиентом. Если recv() возвращает -1, то отметьте errno или эквивалент фактической ошибки (за небольшим исключением, большинство ошибок следует рассматривать как несравнимое отсоединение). Дело в неожиданных разъединениях заключается в том, что они могут занять много времени для обнаружения ОС, поэтому вам придется либо включить поддержку TCP-авитов, либо потребовать от клиента отправки данных на сервер на регулярной основе. Если ничего не получено от клиента в течение определенного периода времени, просто предположите, что клиент ушел и закрыл конец вашего соединения. Если клиент хочет, он может снова подключиться.

+0

Я думаю, что вы неправильно поняли вопрос. Кажется, он использует Netty на сервере. – EJP

0

Если вы прочитали соединение, которое было закрыто одноранговым узлом, вы получите указание конца потока в зависимости от API. Если вы пишете на такое соединение, вы получите IOException: «reset connection». TCP не предоставляет другого способа обнаружения закрытого соединения.

TCP keep-alive (a) отключен по умолчанию и (b) работает только каждые два часа по умолчанию при включении. Это, вероятно, не то, что вы хотите. Если вы используете его, и вы читаете или записываете после того, как обнаружили, что соединение нарушено, вы получите ошибку сброса выше,

+0

В Windows 2000 и более поздних версиях вы можете запрограммировать заданный интервал поддержки TCP для каждого соединения на основе «WSAIoctl (SIO_KEEPALIVE_VALS)». –

Смежные вопросы