
Установление и разрыв TCP соединения
TCP это протокол, ориентированный на соединение. Перед тем как какая-либо сторона может послать данные другой, между ними должно быть установлено соединение. Далее мы подробно рассмотрим, как устанавливается TCP соединение и как оно разрывается.
Рисунок 1 Временная диаграмма установления и разрыва соединения.
Протокол установления соединения
Перейдем к деталям TCP протокола, которые показаны на рисунке 1. Чтобы установить TCP соединение, необходимо:
Запрашивающая сторона (которая, как правило, называется клиент) отправляет SYN сегмент, указывая номер порта сервера, к которому клиент хочет подсоединиться, и исходный номер последовательности клиента (в данном примере ISN, J). Это сегмент номер 1.
Сервер отвечает своим сегментом SYN, содержащим исходный номер последовательности сервера (сегмент 2). Сервер также подтверждает приход SYN клиента с использованием ACK (ISN клиента плюс один). На SYN используется один номер последовательности.
Клиент должен подтвердить приход SYN от сервера с использованием ACK (ISN сервера плюс один(K = J+1), сегмент 3).
Этих трех сегментов достаточно для установления соединения. Часто это называется трехразовым рукопожатием (three-way handshake).
Считается, что сторона, которая посылает первый SYN, активизирует соединение (активное открытие). Другая сторона, которая получает первый SYN и отправляет следующий SYN, принимает пассивное участие в открытии соединения (пассивное открытие). (В разделе "Одновременное открытие" подробно описывается процедура открытия соединения, где обе стороны считаются активными при установлении соединения.)
Когда каждая сторона отправила свой SYN чтобы установить соединение, она выбирает исходный номер последовательности (ISN) для этого соединения. ISN должен меняться каждый раз, поэтому каждое соединение имеет свой, отличный от других ISN. RFC 793 [Postel 1981c] указывает, что ISN является 32-битным счетчиком, который увеличивается на единицу каждые 4 микросекунды. Благодаря номерам последовательностей, пакеты, задержавшиеся в сети и доставленные позже, не воспринимаются как часть существующего соединения.
Протокол разрыва соединения
Для того чтобы установить соединение, необходимо 3 сегмента, а для того чтобы разорвать - 4. Это объясняется тем, что TCP соединение может быть в наполовину закрытом состоянии. Так как TCP соединение полнодуплексное (данные могут передвигаться в каждом направлении независимо от другого направления), каждое направление должно быть закрыто независимо от другого. Правило заключается в том, что каждая сторона должна послать FIN, когда передача данных завершена. Когда TCP принимает FIN, он должен уведомить приложение, что удаленная сторона разрывает соединение и прекращает передачу данных в этом направлении. FIN обычно отправляется в результате того, что приложение было закрыто.
Получение FIN означает только, что в этом направлении прекращается движение потока данных. TCP, получивший FIN, может все еще посылать данные. Несмотря на то, что приложение все еще может посылать данные при наполовину закрытом TCP соединении, на практике только некоторые (совсем немного) TCP приложения используют это. Обычным является тот сценарий, который показан на рисунке 1. Опишем наполовину закрытый режим более подробно в разделе "Наполовину закрытый TCP".
Можно сказать, что та сторона, которая первой закрывает соединение (отправляет первый FIN), осуществляет активное закрытие, а другая сторона (которая приняла этот FIN) осуществляет пассивное закрытие. Обычно, одна сторона осуществляет активное закрытие, а другая пассивное, однако в разделе "Одновременное закрытие" этой главы мы увидим, что обе стороны могут осуществить активное закрытие.
Сегмент номер 4 на рисунке 1 приводит к закрытию соединения. При этом TCP клиент вынужден послать FIN, закрывая поток данных от клиента к серверу.
Когда сервер получает FIN, он отправляет назад ACK с принятым номером последовательности плюс один (сегмент 5). На FIN тратится один номер последовательности, так же как на SYN. В этот момент TCP сервер также доставляет приложению признак конца файла (end-of-file) (чтобы выключить сервер). Затем сервер закрывает свое соединение, что заставляет его TCP послать FIN (сегмент 6), который клиент должен подтвердить (ACK), увеличив на единицу номер принятой последовательности (сегмент 7).
Соединения обычно устанавливаются клиентом, то есть первый SYN двигается от клиента к серверу. Однако любая сторона может активно закрыть соединение (послать первый FIN). Часто, однако, именно клиент определяет, когда соединение должно быть разорвано, так как процесс клиента в основном управляется пользователем.
Наполовину закрытый tcp
TCP предоставляет возможность одному участнику соединения прекратить передачу данных, однако все еще получать данные от удаленной стороны. Это называется наполовину закрытый TCP.
Чтобы использовать эту характеристику программного интерфейса, необходимо предоставить возможность приложению сказать: "Я закончило передачу данных, поэтому посылаю признак конца файла (end-of-file) (FIN) на удаленный конец, однако я все еще хочу получать данные с удаленного конца до тех пор, пока он мне не пошлет признак конца файла (end-of-file) (FIN)."
На рисунке 2 показан стандартный сценарий для полузакрытого TCP. Мы показали клиента с левой стороны, он инициирует полузакрытый режим, однако это может сделать любая сторона. Первые два сегмента одинаковы: FIN от инициатора, за ним следует ACK и FIN от принимающего. Однако дальше сценарий будет отличаться от того, который приведен на рисунке 1, потому что сторона, которая приняла приказ "полузакрыть", может все еще посылать данные. Мы показали только один сегмент данных, за которым следует ACK, однако в этом случае может быть послано любое количество сегментов данных. Когда конец, который получил приказ "полузакрыть", осуществил передачу данных, он закрывает свою часть соединения, в результате чего посылается FIN, при этом признак конца файла доставляется приложению, которое инициировало "полузакрытый" режим. Когда второй FIN подтвержден, соединение считается полностью закрытым.
Рисунок 2 TCP в полузакрытом режиме.