Книга: UNIX: разработка сетевых приложений

Завершение соединения TCP

Завершение соединения TCP

В то время как для установления соединения необходимо три сегмента, для его завершения требуется четыре сегмента.

1. Одно из приложений первым вызывает функцию close, и мы в этом случае говорим, что конечная точка TCP выполняет активное закрытие (active close). TCP этого узла отправляет сегмент FIN, обозначающий прекращение передачи данных.

2. Другой узел, получающий сегмент FIN, выполняет пассивное закрытие (passive close). Полученный сегмент FIN подтверждается TCP. Получение сегмента FIN также передается приложению как признак конца файла (после любых данных, которые уже стоят в очереди, ожидая приема приложением), поскольку получение приложением сегмента FIN означает, что оно уже не получит никаких дополнительных данных по этому соединению.

3. Через некоторое время после того как приложение получило признак конца файла, оно вызывает функцию close для закрытия своего сокета. При этом его TCP отправляет сегмент FIN.

4. TCP системы, получающей окончательный сегмент FIN (то есть того узла, на котором произошло активное закрытие), подтверждает получение сегмента FIN.

Поскольку сегменты FIN и ACK передаются в обоих направлениях, обычно требуется четыре сегмента. Мы используем слово «обычно», поскольку в ряде сценариев сегмент FIN на первом шаге отправляется вместе с данными. Кроме того, сегменты, отправляемые на шаге 2 и 3, исходят с узла, выполняющего пассивное закрытие, и могут быть объединены. Соответствующие пакеты изображены на рис. 2.3.


Рис. 2.3. Обмен пакетами при завершении соединения TCP

Сегмент FIN занимает 1 байт пространства порядковых номеров аналогично SYN. Следовательно, сегмент ACK каждого сегмента FIN — это порядковый номер FIN плюс один.

Возможно, что между шагами 2 и 3 какие-то данные будут переданы от узла, выполняющего пассивное закрытие, к узлу, выполняющему активное закрытие. Это состояние называется частичным закрытием (half-close), и мы рассмотрим его во всех подробностях вместе с функцией shutdown в разделе 6.6.

Отправка каждого сегмента FIN происходит при закрытии сокета. Мы говорили, что для этого приложение вызывает функцию close, но нужно понимать, что когда процесс Unix прерывается либо произвольно (при вызове функции exit или при возврате из функции main), либо непроизвольно (при получении сигнала, прерывающего процесс), все его открытые дескрипторы закрываются, что также вызывает отправку сегмента FIN любому соединению TCP, которое все еще открыто.

Хотя на рис. 2.3 мы продемонстрировали, что активное закрытие выполняет клиент, на практике активное закрытие может выполнять любой узел: и клиент, и сервер. Часто активное закрытие выполняет клиент, но с некоторыми протоколами (особенно HTTP) активное закрытие выполняет сервер.

Оглавление книги


Генерация: 2.565. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз