2.6.3.Транспортный протокол

Транспортный протокол (Transport Control Protocol, TCP) служит для передачи данных между сетевым и прикладным уровнями. По сравнению с UDP TCP устроен гораздо сложнее, ему приходится обеспечивать надежную, потоковую, ориентированную на соединение службу доставки данных. Другими словами, TCP сам следит за доставкой данных, а также за правильной последовательностью передаваемых пакетов. В отличие от TCP протокол пользовательских датаграмм (UDP) доставки данных не гарантирует. Не обеспечивает он и правильной последовательности прихода датаграмм.

TCP динамически управляет потоком данных в соединении, пытаясь оптимизировать пропускную способность сети, то есть увеличивает производительность доставки пакетов в Интернет, насколько это вообще возможно. Если буфер приемника данных на принимающем конце переполняется, TCP просит передающую сторону снизить скорость передачи.

Для обеспечения надежной доставки и правильной последовательности данных в потоке TCP пользуется подтверждениями. Как только пункт назначения принимает блок данных, он передает подтверждение о приеме источнику данных. Каждый раз при передаче сообщения модуль TCP запускает специальный таймер. По истечении заданного в нем времени и не получении подтверждения TCP повторяет попытку передать свое сообщение.

TCP не посылает один пакет, ожидая прихода подтверждения, чтобы послать следующий. Вместо этого он использует принцип “скользящего окна”. Этот принцип позволяет послать несколько сообщений и только потом ожидать подтверждения.

TCP как бы накладывает окно на поток данных, ожидающих передачи, и передает все данные, попавшие в окно. Приняв подтверждение о доставке всех данных, TCP перемещает окно дальше по потоку и передает следующие попавшие в него сообщения. Работая сразу с несколькими сообщениями, TCP может одновременно “выставить” их на сетевой канал и только потом ожидать прихода подтверждения. Метод скользящего окна значительно увеличивает производительность соединения, а также эффективность циклов обмена сообщениями и подтверждениями об их доставке.

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

На самом деле TCP задает размер окна в байтах. То есть размер окна по умолчанию может равняться нескольким тысячам байтов, а не восьми, десяти и двенадцати байтам, как в предыдущем примере. Как правило, модуль TCP передает несколько сегментов, прежде чем скользящее окно заполнится целиком. Большинство систем в Интернет устанавливают окно равным по умолчанию 4096 байтам. Иногда размер окна равен 8192 или 16 384 байтам.

Сообщение TCP

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

Сегмент TCP состоит из TCP-заголовка, TCP-опций и данных, переносимых сегментом.

32 бита

0                                                              15

16                                                         31

Порт-передатчик (16 бит)

Порт-приемник (16 бит)

32-битный номер последовательности

32-битный номер подтверждения

Длина заголовка (4 бита)

Зарезервировано (6 бит)

URG

ACK

PSH

PST

SYN

FIN

Размер окна (16 бит)

Контрольная сумма TCP (16 бит)

Указатель на данные для неотложной обработки (16 бит)

Опции (если есть)

Заполнение (если нужно)

Область данных (необязательно)

Подпись: Рис. 2.14. Структура сегмента TCP

Для установления и прекращения соединения, а также для отправки и получения подтверждений TCP заголовок имеет поля “номер последовательности”, “номер подтверждения” и поля флагов. Каждый раз, желая что-нибудь передать по протоколу TCP, программа-приложение запрашивает модуль TCP установить соединение. Модуль TCP в свою очередь шлет сообщение TCP с установленным флагом SYN (синхронизации) удаленному порту, с которым программа-клиент хочет установить соединение.

Флаг синхронизации указывает принимающей стороне (серверу, например), что программа-клиент желает установить соединение. Вместе с флагом SYN сообщение TCP несет в себе 32-битный номер последовательности, размещенный модулем TCP в поле “номер последовательности”. TCP-модуль сервера отвечает сегментом TCP с установленными флагом подтверждения (АСК) и номером подтверждения. Сетевые компьютеры пользуются разнообразными методами для выбора начального номера последовательности.

Таблица 2.8

Назначение полей заголовка TCP

Поле заголовка

Назначение

Порт-передатчик

Обозначает порт протокола приложения-источника данных

Порт-приемник

Обозначает порт протокола приложения-получателя данных

Номер последовательности

Определяет первый байт данных в области данных сегмента TCP

Номер подтверждения

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

Длина заголовка

Длина TCP-заголовка, измеренная в 32-разрядных словах

Флаг URG

Если установлен, то извещает принимающий модуль TCP о том, что в сегменте находятся данные для неотложной обработки

Флаг АСК

Указание принимающему модулю TCP на то, что поле "Номер подтверждения" содержит соответствующие данные

Флаг PSH

Требование принимающему модулю TCP передать данные приложению-получателю немедленно

Флаг RST

Запрос принимающему модулю TCP сбросить соединение

Флаг SYN

Запрос принимающему модулю TCP синхронизировать номера последовательности

Флаг FIN

Сообщение принимающему модулю TCP об окончании передачи

Размер окна

Сообщение принимающему модулю TCP о количестве байтов, которое способен принять модуль-передатчик

Контрольная сумма TCP

Служит для обнаружения поврежденных при передаче данных

Указатель на неотложные данные

Указывает на последний байт данных, требующих неотложной обработки, находящихся в области данных сегмента TCP

Опции

Обычно используются совместно с опцией максимальная длина сегмента (MSS)

Начальный номер последовательности представляет собой число, пересылаемое модулем-передатчиком TCP модулю-приемнику TCP. Передавая начальный номер, TCP-модуль как бы сообщает корреспонденту: “Эй, я хочу установить с тобой соединение. Нумерация данных в потоке от меня начинается с этого числа”.

Сервер-приемник сообщения, получив запрос на установление соединения, посылает обратно сообщение, содержащее его собственный начальный номер. Модуль TCP генерирует какое-либо число, совершенно не зависящее от числа, посланного TCP-клиентом. Другими словами, сервер как бы сообщает: “Привет! Я получил твой запрос на TCP-соединение и высылаю номер, с которого начнется нумерация моих собственных данных”.

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

Подтверждение доставки данных

В TCP-заголовке самого первого, начального, сообщения-ответа сервера модуль TCP устанавливает два флага: синхронизации (SYN), чтобы известить модуль TCP клиента о том, что в сообщении содержится начальный номер последовательности сервера, и подтверждения (АСК), чтобы заставить клиента изучить содержимое поля “подтверждение”.

TCP-модуль сервера использует номер последовательности, принятый от клиента, чтобы сконструировать на его основе собственный номер подтверждения. Номер подтверждения всегда указывает на номер сообщения, которое сервер рассчитывает получить следующим. Таким образом, в начальном сообщении-ответе сервера содержится номер последовательности клиента, увеличенный на единицу.

Соединение установлено

До передачи любых данных модуль TCP клиента, запросивший соединение, должен подтвердить начальное сообщение-ответ, пришедшее от модуля TCP сервера. То есть, когда модуль TCP клиента получает начальное сообщение-ответ от сервера, он должен посылать “подтверждение подтверждения”. (На самом деле клиент подтверждает запрос сервера на синхронизацию обмена.)

Сообщение, посланное TCP-модулем клиента, тоже будет содержать установленный флаг “подтверждение”. В поле “номер подтверждения” TCP-модуль клиента размещает начальный номер последовательности, принятый от сервера, увеличенный на единицу. (Теперь TCP-модуль клиента не устанавливает флаг синхронизации, так как обе стороны соединения уже синхронизировались, то есть договорились о начальных номерах своих последовательностей.) Другими словами, между TCP-модулями происходит обмен данными, состоящий из трех стадий:

1  TCP-модуль клиента пытается установить TCP-соединение, посылая запрос на синхронизацию, содержащий среди прочего начальный номер последовательности.

2  TCP-модуль сервера подтверждает прием запроса на установление соединения и в свою очередь шлет клиенту запрос на синхронизацию с собственным начальным номером последовательности.

3  TCP-модуль клиента подтверждает прием запроса сервера на синхронизацию.

Номер последовательности

Номер последовательности однозначно идентифицирует байт данных в потоке данных TCP. Как следует из названия, номера последовательности последовательны, то есть следуют один за другим. Однако номера последовательности разных соединений TCP необязательно начинаются с одного и того же числа. Номер последовательности, устанавливаемый в каждом сегменте TCP, идентифицирует первый байт в сообщении. То есть является смещением относительно начала потока данных. Номер последовательности — то же самое, что счетчик переданных байтов. Он как бы говорит: “Первый байт этого пакета — это номер байта (номер последовательности) в потоке данных”.

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

1  Модуль TCP клиента передает сегмент TCP, содержащий байты с 1 по 500. Номер последовательности, записанный в поле “номер последовательности” сегмента, равен 1251.

2  Модуль TCP клиента передает сегмент TCP, содержащий байты с 501 по 1000. Номер последовательности равен 1751.

3  Следующий сегмент, посланный модулем TCP клиента, содержит байты с 1001 по 1500 с номером последовательности, равным 2251.

4  Наконец, модуль TCP клиента передает данные с 1501 байта по 2000 и устанавливает номер последовательности равным 2751.

TCP-модуль сервера в нашем примере шлет следующие сообщения:

1  Приняв первый сегмент от клиента, TCP-модуль сервера отвечает пакетом-подтверждением с номером подтверждения 1751. Сервер как бы говорит:

“Эй, я принял твои данные, и следующий сегмент, который я надеюсь получить, должен содержать номер последовательности 1751”.

2  Приняв второй сегмент, TCP-модуль сервера шлет номер подтверждения, установленный в 2251.

3  Приняв третий сегмент, TCP-модуль сервера шлет номер подтверждения, равный 2751.

4  Приняв четвертый сегмент, TCP-модуль сервера шлет номер подтверждения, равный 3251. (В данный момент TCP-модуль сервера не знает, что передача данных окончена — TCP-модуль клиента еще не известил об этом.)

Дуплексные сетевые службы

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

С точки зрения TCP-модуля клиента, номер последовательности отсчитывает или идентифицирует данные, посылаемые клиентом в сторону TCP-модуля сервера. Номер подтверждения в сегментах, посланных TCP-модулем клиента, с его точки зрения идентифицирует данные, принятые от TCP-модуля сервера.

Окончание соединения TCP

Соединение TCP заканчивается обменом пакетами, состоящим из двух стадий. Каждая из сторон, как сервер, так и клиент, может предложить другой закончить соединение. Для этого сторона-инициатор обмена высылает пакет с установлен­ным флагом “окончание обмена” (FIN). В силу дуплексной природы протокола TCP оба потока данных независимы и должны быть завершены по отдельности. Даже после закрытия соединения (завершения передачи данных) одной из сторон соединения она в состоянии продолжать прием данных от другой стороны соединения.

Установленный в пакете флаг FIN является сигналом, означающим, что одна сторона прекратила передачу данных. Приход сообщения-подтверждения от другой стороны означает, что обе стороны договорились прекратить обмен данными в одном направлении. Начиная с этого момента, одна из сторон соединения будет молчаливо принимать данные, не делая никаких замечаний по их поводу, а другая молчаливо посылать, не ожидая никаких комментариев. Окончание (закрытие) TCP-соединения — двухступенчатый процесс. Одна сторона выполняет активное закрытие, а другая — пассивное. Закрытие активно, если вызвано по инициативе данной стороны, и, наоборот, пассивно, если вызвано противоположной стороной соединения. Сторона, первой высылающая пакет с установленным флагом “окончание соединения”, является активной. Как правило, модуль TCP, принявший пакет с установленным флагом “окончание соединения”, инициирует пассивное окончание соединения. Это просто значит, что пассивная сторона также посылает сообщение с установленным флагом окончания. Другими словами, сторона, принявшая сообщение об окончании первой, отвечает: “Хорошо, если тебе нечего больше послать, то и мне тоже нечего послать тебе”. После того, как обе стороны выслали друг другу сообщения об окончании и получили подтверждения о доставке этих сообщений, соединение TCP считается действительно законченным (закрытым).

Порт источника и порт получателя

16-битные поля источника и получателя однозначно определяют посылающие и принимающие данные приложения или прикладные протоколы. Номера портов источника и получателя в совокупности с IP-адресами сетевых компьютеров (в IP-заголовке) однозначно идентифицируют любое TCP-соединение. Каждая из сторон TCP-соединения называется сокетом (socket).

Номер последовательности

32-битное поле номера последовательности обозначает первый байт данных из области данных сегмента TCP. Оно соответствует смещению этого байта относительно начала потока данных. Каждый байт в потоке данных может быть идентифицирован при помощи номера последовательности.

Номер подтверждения

32-битное поле номера подтверждения обозначает байт данных, который принимающая сторона рассчитывает получить следующим в потоке данных. Например, если последний принятый байт имел номер 500, модуль TCP установит номер подтверждения равным 501.

Длина заголовка

Как и в заголовке IP, поле длины заголовка TCP состоит из четырех битов, обозначающих длину заголовка, измеренную в 32-битных словах. Как и заголо­вок IP, заголовок TCP обычно имеет длину в 20 байтов. Область данных начинается сразу после заголовка TCP. Таким образом, модуль TCP определяет место, где начинаются данные и кончается заголовок, просто прибавляя поле “длина заголовка”, умноженное на четыре байта (32 бита), к первому байту сегмента данных.

Флаги

Заголовок TCP содержит шесть однобитных полей флагов. Это флаги синхронизации (SYN), подтверждения (АСК) и флаг окончания соединения (FIN).

Флаг URG

Данный флаг сообщает принимающему модулю TCP о том, что указатель на данные, требующие немедленной обработки, в поле “неотложные данные” установлен, то есть указывает на них. (Модуль TCP должен обработать неотложные данные до того, как обрабатывать что-либо еще.)

Флаг АСК

Установленный флаг сообщает принимающему модулю TCP, что поле “номер подтверждения” содержит правильный номер подтверждения. Данный флаг служит обеспечению надежной передачи данных.

Флаг PSH

Установленный флаг PUSH требует от принимающего модуля TCP вытолкнуть (push), то есть немедленно выслать принятый сегмент данных приложению-получателю. Как правило, модуль TCP буферизует принимаемые данные. То есть он не доставляет каждый сегмент по отдельности, а ждет, пока его буфер наполнится, а затем доставляет все принятые сегменты за один раз. Флаг PSH запрещает размещать сегменты данных в буфере. Telnet, например, устанавливает этот флаг. Коды нажатых клавиш  незамедлительно попадают на сервер Telnet, с которым работает пользователь. Такое поведение устраняет возможные задержки в выдаче эха от сервера — большинство пользователей Telnet желают сразу видеть на экране то, что они печатают.

Флаг RST

Данный флаг запрашивает у принимающего модуля TCP сброс соединения. TCP устанавливает флаг RST, если с соединением случилась какая-либо проблема. Большинство приложений просто прекращает работу, приняв этот флаг. Флаг RST может применяться в сложных разработках для контроля повреждений в сети, сбоев в работе оборудования и сетевых программ.

Флаг SYN

Флаг SYN просит принимающий модуль TCP синхронизировать номера последовательности. Вы уже знаете, что этот флаг используется на этапе установления соединения, чтобы сообщить приемнику TCP о том, что источник готовится передать новый поток данных.

Флаг FIN

Флаг сообщает принимающему модулю TCP о том, что источник закончил передавать данные. Этот флаг заканчивает соединение только в том направлении, в каком был послан. Чтобы закончить соединение полностью, принимающий модуль TCP должен также послать сообщение с установленным флагом FIN.

Размер окна

16-битное поле “размер окна” сообщает принимающему модулю TCP количество байтов, которое собирается принять передатчик. TCP использует скользящие окна переменной длины для увеличения производительности и оптимизации пропускной способности сети. Значение данного поля определяет размер этого скользящего окна. Как правило, оно равняется нескольким тысячам байтов.

Контрольная сумма TCP

Как и в случае UDP, 16-битное поле контрольной суммы TCP содержит сумму, вычисленную по области данных. Протокол требует от передатчика, чтобы он включил вычисленную контрольную сумму в поле, а от приемника — чтобы он вычислил ее повторно и сравнил результаты.

Контрольные суммы UDP и TCP вычисляются похожим образом. Однако в случае UDP включать контрольную сумму в датаграмму не обязательно. Напротив, протокол TCP обязывает вставлять контрольную сумму в каждый переданный сегмент данных.

Указатель неотложных данных

16-битное поле указателя определяет положение байта данных в области данных сегмента TCP. Указатель и флаг неотложных данных извещают принимающий модуль TCP о том, что некоторые требующие немедленной обработки данные находятся в сегменте и указывают модулю на них.

Опции

Так же, как и у IP, заголовок TCP содержит необязательное поле “опции” (options). В ходе установления соединения модули TCP договариваются о максимальной длине сегмента (MSS) и устанавливают соответствующую опцию. Смысл максимальной длины сегмента тот же, что и у максимальной длины передаваемого блока (MTU) физического уровня сети. Максимальная длина сегмента определяет максимальный размер сегмента, который может быть передан по соединению TCP. TCP оптимизирует пропускную способность сети, увеличивая ее производительность. Опция максимальной длины сегмента позволяет воспользоваться самым большим размером блока данных, который еще можно передать. Опция MSS устанавливается только в тех сообщениях, в которых уже установлен флаг SYN. Однако опция MSS не является предметом обсуждения между обоими модулями. Каждый из модулей TCP просто сообщает другому тот MSS, который он в состоянии принять. Если модуль TCP по каким-либо причинам не передает MSS, его партнер считает, что нужно пользоваться MSS, равным по умолчанию 536 байтам.