Временная метка Timestamp optionПРИМЕЧАНИЕЧтобы обеспечить совместимость с более ранними реализациями, в которых не поддерживается этот параметр, применяются следующие правила. TCP может отправить параметр со своим сегментом SYN в процессе активного открытия сокета. Но он может масштабировать свое окно, только если другой конец связи также отправит соответствующий параметр со своим сегментом SYN. Эта логика предполагает, что недоступные в данной реализации параметры просто игнорируются. Это общее и необходимое требование, но, к сожалению, его выполнение не гарантировано для всех реализаций.
Перечисленные выше параметры поддерживаются большинством реализаций. Последние два параметра иногда называются «параметрами RFC 1323», они были описаны именно этим стандартом [53]. Они также часто именуются параметрами для «канала с повышенной пропускной способностью», поскольку сеть с широкой полосой пропускания или с большой задержкой называется каналом с повышенной пропускной способностью , или, если перевести дословно, длинной толстой трубой ( long fat pipe ). В главе 24 [111] эти новые параметры описаны более подробно.
Завершение соединения 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) активное закрытие выполняет сервер.
Диаграмма состояний TCP
диаграммы состояний TCP state transition diagramРис. 2.4. Диаграмма состояний TCP
Для соединения определено 11 различных состояний, а правила TCP предписывают переходы от одного состояния к другому в зависимости от текущего состояния и сегмента, полученного в этом состоянии. Например, если приложение выполняет активное открытие в состоянии CLOSED (Закрыло), TCP отправляет сегмент SYN, и новым состоянием становится SYN_SENT (Отправлен SYN). Если затем TCP получает сегмент SYN с сегментом ACK, он отправляет сегмент ACK, и следующим состоянием становится ESTABLISHED (Соединение установлено). В этом последнем состоянии проходит большая часть обмена данными.
Две стрелки, идущие от состояния ESTABLISHED, относятся к разрыву соединения. Если приложение вызывает функцию close перед получением признака конца файла (активное закрытие), происходит переход к состоянию FIN_WAIT_1 (Ожидание FIN 1). Но если приложение получает сегмент FIN в состоянии ESTABLISHED (пассивное закрытие), происходит переход в состояние CLOSE_WAIT (Ожидание закрытия).
Мы отмечаем нормальные переходы клиента с помощью более толстой сплошной линии, а нормальные переходы сервера с помощью штриховой линии. Мы также должны отметить, что существуют два перехода, о которых мы не говорили: одновременное открытие (когда оба конца связи отправляют сегменты SYN приблизительно в одно время, и эти сегменты пересекаются в сети) и одновременное закрытие (когда оба конца связи отправляют сегменты FIN). В главе 18 [111] содержатся примеры и описания обоих этих сценариев, которые хотя и возможны, но встречаются достаточно редко.