Поля Порядковый номер и Номер подтверждения выполняют свою обычную функцию. Обратите внимание: поле Номер подтверждения относится к следующему по порядку ожидаемому байту, а не к последнему полученному. Это накопительное подтверждение (cumulative acknowledgement), так как один номер объединяет в себе информацию обо всех полученных данных. Сфера его применения не выходит за рамки потерянных данных. Оба поля 32-разрядные, так как в TCP-потоке нумеруется каждый байт данных.
Рис. 6.31. Заголовок TCP
Поле Длина TCP-заголовка содержит размер TCP-заголовка, выраженный в 32-разрядных словах. Эта информация необходима, так как поле Параметры, а вместе с ним и весь заголовок может быть переменной длины. По сути, это поле указывает смещение от начала сегмента до поля данных, измеренное в 32-битных словах. Это то же самое, что длина заголовка.
Следом идет неиспользуемое 4-битное поле. Тот факт, что эти биты не используются уже в течение 30 лет (а востребованными оказываются только 2 бита изначально 6-битного поля), является свидетельством того, насколько хорошо продуман дизайн TCP. Иначе протоколы использовали бы эти биты, чтобы справиться с недостатками TCP.
Затем следуют восемь 1-битовых флагов. CWR и ECE сообщают о перегрузках сети в случае, если используется явное уведомление о насыщении (см. RFC 3168). Когда TCP-приемник узнает, что сеть перегружена, он с помощью флага ECE передает TCP-отправителю сигнал ECN-эхо, предлагая ему уменьшить скорость отправки. После того как TCP-приемник уменьшил скорость отправки, он сообщает об этом TCP-приемнику с помощью флага CWR с сигналом Окно насыщения уменьшено, после чего приемник перестает передавать сигнал ECN-эхо. Подробнее о роли явных уведомлений о перегрузке в контроле перегрузки TCP мы поговорим в разделе 6.5.10.
Бит URG устанавливается в 1 в случае использования поля Указатель на срочные данные, содержащего смещение в байтах от текущего порядкового номера байта до места расположения срочных данных. Таким образом, в протоколе TCP реализуются прерывающие сообщения. Как уже упоминалось, этот метод позволяет отправителю передать получателю сигнал, не вовлекая в это TCP; он используется редко.
Если бит ACK установлен в 1, значит, поле Номер подтверждения содержит осмысленные данные. Для большинства пакетов это так. В противном случае данный сегмент не содержит подтверждения, и поле Номер подтверждения просто игнорируется.
Бит PSH является, по сути, PUSH-флагом, с помощью которого отправитель просит получателя доставить данные приложению сразу по получении пакета, а не хранить их в буфере, пока тот не наполнится. (Получатель может заниматься буферизацией для достижения большей эффективности.)
Бит RST используется для внезапного сброса состояния соединения, которое из-за сбоя хоста или по другой причине попало в тупиковую ситуацию. Кроме того, он используется для отказа от неверного сегмента или от попытки создать соединение. Если вы получили сегмент с установленным битом RST, это означает наличие какой-то проблемы.
Бит SYN применяется для установки соединения. У запроса соединения бит SYN = 1, а бит ACK = 0, это означает, что поле подтверждения не используется. Но в ответе на этот запрос содержится подтверждение, поэтому значения этих битов в нем равны: SYN = 1, ACK = 1. Таким образом, бит SYN используется для обозначения как сегментов CONNECTION REQUEST, так и CONNECTION ACCEPTED, а бит ACK — чтобы отличать их друг от друга.
Бит FIN используется для разрыва соединения. Он указывает на то, что у отправителя больше нет данных для передачи. Однако, даже закрыв соединение, процесс может продолжать получать данные в течение неопределенного времени. У сегментов с битами FIN и SYN есть порядковые номера, что гарантирует правильный порядок их выполнения.
Управление потоком в протоколе TCP осуществляется при помощи скользящего окна переменного размера. Поле Размер окна сообщает, сколько байт может быть послано после байта, получившего подтверждение. Значение поля Размер окна может быть равно нулю, это означает, что все байты вплоть до Номер подтверждения-1 получены, но получатель еще не обработал эти данные, и поэтому остальные байты он пока принять не может. Разрешение на дальнейшую передачу может быть получено путем отправки сегмента с таким же значением поля Номер подтверждения и ненулевым значением поля Размер окна.
В главе 3 мы обсуждали протоколы, в которых подтверждения приема кадров были связаны с разрешениями на продолжение передачи. Эта связь была следствием жестко закрепленного размера скользящего окна в этих протоколах. В ТСР подтверждения отделены от разрешений на передачу данных. В сущности, приемник может сказать: «Я получил байты вплоть до k-го, но я сейчас не хочу продолжать прием данных». Такое разделение (выражающееся в скользящем окне переменного размера) придает протоколу дополнительную гибкость. Ниже мы обсудим этот аспект более детально.
Поле Контрольная сумма служит для повышения надежности. Как и в случае UDP, оно содержит контрольную сумму заголовка, данных и псевдозаголовка. Но в отличие от UDP псевдозаголовок этого поля содержит номер протокола TCP (6), а контрольная сумма является обязательной. Для более подробной информации см. раздел 6.4.1.
Поле Параметры предоставляет дополнительные возможности, не покрываемые стандартным заголовком. Существует множество параметров и некоторые из них широко используются. Они имеют разную длину, кратную 32 битам (лишнее место заполняется нулями), и могут доходить до отметки в 40 байт — максимального размера заголовка TCP. При установлении соединения факультативные поля могут использоваться для того, чтобы договориться с противоположной стороной или просто сообщить ей о характеристиках этого соединения. Существуют поля, сохраняющиеся в течение всего времени жизни соединения. Все факультативные поля имеют формат Тип-Длина-Значение.
С помощью одного из таких полей каждый хост может указать максимальный размер сегмента (MSS, Maximum Segment Size), который он может принять. Чем больше размер используемых сегментов, тем выше эффективность, так как при этом снижается удельный вес накладных расходов в виде 20-байтных заголовков, однако не все хосты способны принимать очень большие сегменты. Хосты могут сообщить друг другу максимальный размер сегмента во время установки соединения. По умолчанию этот размер равен 536 байтам. Все хосты обязаны принимать TCP-сегменты размером 536 + 20 = 556 байт. Для каждого из направлений может быть установлен свой максимальный размер сегмента.
Для линий с большой скоростью передачи и/или большой задержкой окно размером в 64 Кбайт, соответствующее 16-битному полю, оказывается слишком маленьким. Так, для линии OC-12 (приблизительно 600 Мбит/с) полное окно может быть передано в линию менее чем за 1 мс. Если значение времени распространения сигнала в оба конца составляет 50 мс (что типично для трансконтинентального оптического кабеля), 98 % времени отправитель будет заниматься ожиданием подтверждения. Больший размер окна мог бы улучшить эффективность. Параметр масштаб окна позволяет двум хостам договориться о масштабе окна при установке соединения. Это число позволяет обеим сторонам сдвигать поле Размер окна до 14 разрядов влево, обеспечивая расширение размера окна до 230 байт (1 Гбайт). Большинство реализаций протокола TCP поддерживают эту возможность.