Эффективное программирование TCP-IP

       

Механизм контролеров


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

Если хост на другом конце работает, а приложение - нет, то TCP посылает в ответ сегмент RST. A TCP, отправивший контролер, разрывает соединение и возвращает приложению код ECONNRESET. Обычно так бывает после перезагрузки и удаленного хоста, поскольку, как говорилось в совете 9, если бы завершилось всего лишь приложение на другом конце, то TCP послал сегмент FIN.

Если удаленный хост не посылает в ответ ни АСК, ни RST, то TCP продолжает посылать контролеров, пока не получит сведений, что хост недоступен. В этот момент он разрывает соединение и возвращает приложению код ETIMEDOUT либо, если маршрутизатор прислал ICMP-сообщение о недоступности хоста или сети, соответственно код EHOSTUNREACH или ENETUNREACH.

Первая проблема, с которой сталкиваются приложения, нуждающиеся в немедленном уведомлении, при попытке воспользоваться механизмом контролеров, - это длительность временных интервалов. В соответствии с RFC 1122 [Braden 1989], если TCP реализует механизм контролеров, то по умолчанию время простоя должно быть не менее двух часов. И только после этого можно посылать контролеров. Затем, поскольку АСК, посланный удаленным хостом, доставляется ненадежно, процесс отправки контролеров необходимо несколько раз повторить; и лишь тогда можно разрывать соединение. В системе 4.4BSD отправляется девять контролеров с интервалом 75 с.

Примечание: Точные величины - деталь реализации. В RFC 1122 не говорится о том, сколько и с каким интервалом нужно посылать контролеры, прежде чем разорвать соединение. Утверждается лишь, что реализация не должна интерпретировать отсутствие ответа на посылку одного контролера как индикатор прекращения соединения.


Таким образом, в реализациях на основе BSD для обнаружения потери связи потребуется 2 ч 11 мин 15 с. Этот срок приобретает смысл, если вы понимаете, что назначение контролеров - освободить ресурсы, занятые уже несуществующими соединениями. Такое возможно, например, если клиент соединяется с сервером, а затем хост клиента неожиданно отключается. Без механизма дежурных серверу пришлось бы ждать следующего запроса от клиента вечно, поскольку он не получит FIN

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

В некоторых реализациях разрешено изменять один или оба временных интервала, но это всегда распространяется на систему в целом. Иными словами, изменение затрагивает все TCP-соединения, установленные данной системой, и есть основная причина, по которой механизм контролеров почти бесполезен в качестве средства мониторинга связи. Период, выбранный по умолчанию, слишком велик, а если его сократить, то контролеры перестанут выполнять свою исходную задачу - обнаруживать давно «зависшие» соединения.

В последней версии стандарта POSIX появилась новейшая опция сокета TCP_KEEPALIVE, которая позволяет устанавливать временной интервал для отдельного соединения, но пока она не получила широкого распространения.

Еще одна проблема, связанная с механизмом контролеров, состоит в том, что он не просто обнаруживает «мертвые» соединения, а еще и разрывает их независимо от того, допускает ли это приложение.


Содержание раздела