Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
12_Транспортный уровень TCP.doc
Скачиваний:
7
Добавлен:
06.08.2019
Размер:
327.17 Кб
Скачать

Процедура установления соединения

Чтобы установить TCP соединение, выполняются следующие шаги:

  1. Запрашивающая сторона (которая, как правило, называется клиент) отправляет SYN сегмент, указывая номер порта сервера, к которому клиент хочет подсоединиться, и исходный номер последовательности клиента. Это сегмент номер 1.

  2. Сервер отвечает своим сегментом SYN, содержащим исходный номер последовательности сервера (сегмент 2). Сервер также подтверждает приход SYN клиента с использованием ACK (ISN клиента плюс один). На SYN используется один номер последовательности.

  3. Клиент должен подтвердить приход SYN от сервера с использованием ACK (ISN сервера плюс один, сегмент 3).

Этих трех сегментов достаточно для установления соединения. Часто это называется тройным рукопожатием (three-way handshake).

Обобщенная диаграмма установления и закрытия соединения

Столкновение вызовов в процессе установления соединения отрабатывается следующим образом:

В результате будет установлено только одно соединение, а не два, так как пара конечных точек однозначно определяет соединение. То есть если оба соединения пытаются идентифицировать себя с помощью пары (х, у), делается всего одна табличная запись для (х, у).

Такая достаточно сложная процедура установления соединения необходима для предотвращения проблем, связанных с потерями и задержками пакетов в сети. Важную роль при этом играет исходный номер последовательности клиента ISN. Мы помним, что это 32-битный номер со значением от 1 до 4 294 967 295 (2 в 32-ой степени). ISN при старте системы например после перезагрузки обнуляется, затем в отсутствии установленного соединения каждые 4 микросекунды по отчетам внутреннего таймера он увеличивается на 1. Получается, что цикл уникальности ISN (при условии того, что никакие соединения не устанавливались) составляет примерно 4,55 часа. Поскольку ни один пакет так долго по сети не путешествует, мы можем полагать, что SYN будет абсолютно уникальным.

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

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

Считается, что сторона, которая посылает первый SYN, активизирует соединение (активное открытие). Другая сторона, которая получает первый SYN и отправляет следующий SYN, принимает пассивное участие в открытии соединения (пассивное открытие).

Процедура разрыва соединения

Для того чтобы установить соединение, необходимо 3 сегмента, а для того чтобы разорвать - 4. Это объясняется тем, что TCP соединение может быть в наполовину закрытом состоянии. Так как TCP соединение полнодуплексное (данные могут передвигаться в каждом направлении независимо от другого направления), каждое направление должно быть закрыто независимо от другого. Правило заключается в том, что каждая сторона должна послать FIN, когда передача данных завершена. Когда TCP принимает FIN, он должен уведомить приложение, что удаленная сторона разрывает соединение и прекращает передачу данных в этом направлении. FIN обычно отправляется в результате того, что приложение было закрыто.

Получение FIN означает только, что в этом направлении прекращается движение потока данных. TCP, получивший FIN, может все еще посылать данные.

Соединения обычно устанавливаются клиентом, то есть первый SYN двигается от клиента к серверу. Однако любая сторона может активно закрыть соединение (послать первый FIN).

Модель управления TCP/IP

Этапы, необходимые для установки и разрыва соединения, могут быть представ-

лены в виде модели, имеющей 11 возможных состояний:

Состояние Описание

CLOSED Закрыто. Соединение не является активным и не находится в процессе установки

LISTEN Ожидание. Сервер ожидает входящего запроса

SYN RCVD Прибыл запрос соединения. Ожидание подтверждения

SYN SENT Запрос соединения послан. Приложение начало открывать соединение

ESTABLISHED Установлено. Нормальное состояние передачи данных

FIN WAIT 1 Приложение сообщило, что ему больше нечего передавать

FIN WAIT 2 Другая сторона согласна разорвать соединение

TIMED WAIT Ожидание, пока в сети не исчезнут все пакеты

CLOSING Обе стороны попытались одновременно закрыть соединение

CLOSE WAIT Другая сторона инициировала разъединение

LAST АСК Ожидание, пока в сети не исчезнут все пакеты

В каждом из этих состояний могут происходить разрешенные и запрещенные события. В ответ на какое-либо разрешенное событие может осуществляться определенное действие. При возникновении запрещенных событий сообщается об ошибке.

Каждое соединение начинается в состоянии CLOSED (закрытое). Оно может выйти из этого состояния, предпринимая либо активную (CONNECT), либо пассивную (LISTEN) попытку открыть соединение. Если противоположная сторона осуществляет противоположные действия, соединение устанавливается и переходит в состояние ESTABLISHED. Инициатором разрыва соединения может выступить любая сторона. По завершении процесса разъединения соединение возвращается в состояние CLOSED.

Рассмотрим сводную диаграмму состояний соединения TCP. Типичный случай клиента, активно соединяющегося с пассивным сервером, показан жирными линиями — сплошными для клиента и пунктирными для сервера. Тонкие линии обозначают необычные последовательности событий. Каждая линия маркирована парой событие/действие. Событие может представлять собой либо обращение пользователя к системной процедуре, либо прибытие сегмента (SYN, FIN, АСК или RST), либо, в одном случае, окончание периода ожидания, равного двойному времени жизни пакетов.

Действие может состоять в отправке управляющего сегмента (SYN, FIN ИЛИ RST). Впрочем, может не предприниматься никакого действия, что обозначается прочерком. В скобках приводятся комментарии.

Диаграмму легче всего понять, если сначала проследовать по пути клиента (сплошная жирная линия), а затем — по пути сервера (жирный пунктир). Когда приложение на машине клиента вызывает примитив CONNECT, локальная ТСР- сущность создает запись соединения, помечает его состояние как SYN SENTn посылает SYN - сегмент. Когда прибывает сегмент SYN + АСК, TCP-сущность посылает последний АСК - сегмент тройного рукопожатия и переключается в состояние ESTABLISHED. В этом состоянии можно пересылать и получать данные.

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

Рассмотрим теперь управление соединением с точки зрения сервера. Сервер выполняет примитив LISTEN и переходит в режим ожидания запросов соединения. Когда приходит SYN - сегмент, в ответ на него высылается подтверждение, после чего сервер переходит в состояние SYN RCVD (запрос соединения получен). Когда в ответ на ACK -подтверждение сервера от клиента приходит АСК - сегмент, процедура тройного рукопожатия завершается и сервер переходит в состояние ESTABLISHED. Теперь можно пересылать данные. По окончании выполнения своей задачи клиент запускает примитив CLOSE, в результате чего на сервер прибывает FIN-сетмепт. Теперь сервер выполняет примитив CLOSE, a FIN - сегмент посылается клиенту. Когда от клиента прибывает подтверждение, сервер разрывает соединение и удаляет запись о нем.

Диаграмма состояний передачи TCP

Управление передачей в TCP

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

Отправитель передает четыре сегмента данных (4-7), чтобы заполнить окно объявленное получателем. Затем отправитель останавливается и ожидает подтверждения. Получатель отправляет подтверждение (сегмент 8), однако объявляет окно равное 0. Это означает, что получатель получил данные, однако все они находятся в TCP буферах получателя, потому что приложение не имеет возможности считать данные.

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

Еще один ACK (называемый обновлением окна) посылается через 17,4 миллисекунды и объявляет о том, что получатель теперь может получить следующие 4096 байт. То, что выглядит как подтверждение (ACK), в действительности является обновлением окна, потому что здесь не происходит подтверждения каких-либо вновь полученных данных, а просто объявляется новый размер окна.

Отправитель не обязан передавать данные сразу, как только они приходят от приложения. Также не требуется от получателя посылать подтверждения как можно скорее. Эта свобода действий может использоваться для улучшения производительности.

Отправитель передает свои последние четыре сегмента (10-13) и опять заполняет окно принимающего. Обратите внимание, что сегмент 13 содержит два флаговых бита: PUSH и FIN. После этого следуют еще два подтверждения от принимающего. Они подтверждают последние 4096 байт данных (байты от 4097 до 8192) и FIN (который имеет номер 8193).

Теперь посмотрим, как осуществляется передача данных через TCP соединение в случае, когда приложению требуется пересылка мелких порций данных, на примере интерактивного ввода команд в Rlogin или Telnet соединении. Указанные протоколы используются для удаленной работы на компьютере с обеспечением текстового интерфейса. Для этого ввод каждого символа (каждое нажатие клавиши) генерирует процедуру отправки этого символа на используемый компьютер и подтверждение им получения этого символа (для этого символ пересылается обратно на терминал и только после такого эхо-приема отображается на его экране). В результате каждое нажатие клавиши генерирует 4 TCP сегмента: (1) интерактивный ввод символа от клиента, (2) подтверждение получение символа от сервера, (3) эхо введенного символа от сервера и (4) подтверждение на эхо от клиента. На рисунке показан происходящий обмен данными.

При этом генерируются пакеты размером 41 байт: 20 байт - IP заголовок, 20 байт - TCP заголовок и 1 байт данных. Маленькие пакеты - обычно не проблема для локальных сетей, так как большинство локальных сетей не перегружаются, однако они могут привести к перегрузке глобальной сети. Простое и элегантное решение было предложено в 1984 (John Nagle), которое сейчас называется алгоритмом Нагля.

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

Еще одна проблема, которую должен уметь решать TCP принято называть синдромом «глупого окна». Эта ситуация возникает, когда отправитель передает сегмент с большим количеством байт, заполняет буфер получателя, а приложение получателя считывает из буфера по 1 байту. Тогда в ACK - подтверждении получателя будет установлен размер окна 1 байт и эффективность передачи снизится, а нагрузка на сеть возрастет. Для преодоления этой проблемы Дэвидом Кларком (David Clark) было предложено запретить передачу окна размером в 1 байт.