Гарантирует ли асинхронный прием обнаружение сбоя соединения? - PullRequest
3 голосов
/ 05 декабря 2010

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

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

Интересно, может ли использование асинхронного приема решить проблему обнаружения сбоя соединения? В boost :: asio я бы назвал socket::asynch_read_some(), регистрируя обработчик для асинхронного вызова, в то время как в java.nio я бы настроил канал как неблокирующий и зарегистрировал его в селекторе с флагом интереса OP_READ. Я предполагаю, что правильное обнаружение сбоя соединения означало бы, что в первом случае обработчик будет вызываться с кодом ошибки, отличным от 0, в то время как во втором случае селектор выберет неисправный канал, но последующий read() на канале либо вернет -1, либо бросит IOException.

Гарантируется ли это поведение при асинхронном приеме или могут быть сценарии, в которых после сбоя соединения, например, в boost :: asio, никогда не будет вызываться обработчик или в java.nio селектор никогда не будет выбирать канал?

Большое спасибо.

Ответы [ 2 ]

5 голосов
/ 05 декабря 2010

Я полагаю, что вы имеете в виду проблему полуоткрытое соединение TCP (значение термина RFC 793).В этом случае принимающая ОС никогда не будет получать указание на потерянное соединение, поэтому она никогда не уведомит приложение.Если приложение читает синхронно или асинхронно, это не влияет на него.

Проблема возникает, когда передающая сторона соединения как-то больше не знает о сетевом соединении.Это может произойти, например, когда

  • передающая ОС внезапно завершает работу / перезагружается (отключение питания, сбой ОС / BSOD и т. Д.).

  • передающая сторона закрывает свою сторону, в то время как между двумя сторонами происходит разрыв сети, и очищает свою сторону: например, передающая ОС перезагружается аккуратно во время сбоя, передающая ОС Windows отключается от сети

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

Ваше решение (тайм-аут) является одним из способов решения проблемы, но оно должновключает отправку сообщения передающей стороне.Опять же, не имеет значения, является ли чтение синхронным или асинхронным, просто то, что оно не читает и не ждет бесконечно данных или FIN.Другое решение заключается в использовании функции TCP KEEPALIVE , которая поддерживается некоторыми стеками TCP.Но трудная часть любого обобщенного решения обычно определяет правильное время ожидания , поскольку время ожидания сильно зависит от характеристик конкретного приложения.

4 голосов
/ 05 декабря 2010

Из-за того, как работает TCP, вам обычно приходится отправлять данные, чтобы заметить сбой жесткого соединения, чтобы выяснить, что пакет ACK никогда не будет возвращен. Некоторые протоколы пытаются идентифицировать подобные условия путем периодического использования пакета keep-alive или пакета ping: если одна сторона не получает такой пакет за время X (и, возможно, после попытки и отказа одного из них сама), она может считать соединение разорванным.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...