Читаем Компьютерные сети. 6-е изд. полностью

Когда у приложения заканчиваются данные для передачи, оно выполняет операцию CLOSE, заставляющую локальную TCP-подсистему отправить FIN-сегмент и ждать ответного ACK-сегмента (пунктирный прямоугольник с пометкой «активное разъединение»). Когда прибывает подтверждение, происходит переход в состояние FIN WAIT 2, и одно направление соединения закрывается. Когда приходит встречный FIN-сегмент, в ответ на него также высылается подтверждение, после чего закрывается второе направление. Теперь обе стороны соединения закрыты, но TCP-подсистема ожидает в течение удвоенного максимального времени жизни пакета. Таким образом гарантируется, что ни один пакет этого соединения больше не перемещается по сети, даже если подтверждение было потеряно. Когда период ожидания истекает, TCP-подсистема удаляет запись о соединении.

Илл. 6.39. Конечный автомат TCP-соединения. Жирная сплошная линия показывает нормальный путь клиента. Жирным пунктиром показан нормальный путь сервера. Тонкими линиями обозначены необычные события. Для каждого перехода через косую черту указано, какое событие его вызывает и к выполнению какого действия он приводит

Далее рассмотрим управление соединением с точки зрения сервера. Он выполняет LISTEN и переходит в режим ожидания запросов соединения. Когда приходит SYN-сегмент, в ответ на него высылается подтверждение, после чего сервер переходит в состояние SYN RCVD (запрос соединения получен). Когда в ответ на SYN-подтверждение от клиента приходит ACK-сегмент, процедура «тройного рукопожатия» завершается и сервер переходит в состояние ESTABLISHED. Теперь можно передавать данные.

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

6.5.8. Раздвижное окно TCP

Как уже было сказано выше, управление окном в TCP решает проблемы подтверждения корректной доставки сегментов и выделения буферов получателя. Предположим, у получателя есть 4096-байтный буфер (илл. 6.40). Если отправитель передает 2048-байтный сегмент, который успешно принимается получателем, то последний подтверждает его получение. Однако при этом у получателя остается всего лишь 2048 байт свободного буферного пространства (пока приложение не заберет какое-то количество данных из буфера), о чем он и сообщает отправителю, указывая соответствующий размер окна (2048) и номер следующего ожидаемого байта.

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

При нулевом размере окна отправитель не может отправлять сегменты, за исключением двух случаев. Во-первых, разрешается передавать срочные данные, например, чтобы пользователь мог уничтожить процесс, выполняющийся на удаленном компьютере. Во-вторых, отправитель может отправить 1-байтный сегмент, прося получателя повторить информацию о размере окна и ожидаемом следующем байте. Такой пакет называется пробным сегментом (window probe). Стандарт TCP прямо предусматривает эту возможность для предотвращения тупиковых ситуаций в случае потери объявления о размере окна.

Отправители не обязаны передавать данные сразу же, как только они приходят от приложения. Также никто не требует от получателей отправлять подтверждения как можно скорее. Например, было бы абсолютно логично, если бы TCP-подсистема на илл. 6.40, получив от приложения первые 2 Кбайт данных и зная, что размер окна равен 4 Кбайт, сохранила бы полученные данные в буфере до тех пор, пока не придут еще 2 Кбайт, чтобы передать сегмент из 4 Кбайт. Такая свобода действий может улучшить производительность.

Рассмотрим соединение (к примеру, telnet или SSH) с удаленным терминалом, реагирующим на каждое нажатие клавиши. При наихудшем сценарии, когда символ прибывает к передающей TCP-подсистеме, она создает 21-байтный TCP-сегмент и передает его IP-уровню, который, в свою очередь, отправляет 41-байтную IP-дейтаграмму. На принимающей стороне TCP-подсистема немедленно отвечает 40-байтным подтверждением (20 байт TCP-заголовка и 20 байт IP-заголовка). Затем, когда удаленный терминал прочитает этот байт из буфера, TCP-подсистема отправит обновленную информацию о размере буфера, передвинув окно на 1 байт вправо. Размер этого пакета также составляет 40 байт. Наконец, когда удаленный терминал обработает этот символ, он отправит обратно эхо, включенное в 41-байтный пакет. Итого для каждого введенного с клавиатуры символа пересылается четыре пакета общим размером 162 байта. При дефиците пропускной способности линий этот метод работы нежелателен.

Илл. 6.40. Управление окном в TCP

Перейти на страницу:

Похожие книги