Протокол TCP является одним из важнейших протоколов связи в компьютерных сетях. В этой статье познакомимся с ним поближе.
Что такое транспортные протоколы
Транспортные протоколы (TCP и UDP) используются для передачи информации, то есть это правила или договорённости о передачи информации по сети. Информация передаётся маленькими частями, в протоколе TCP эти части называются сетевыми пакетами. То есть поток информации разбивается на много маленьких пакетов.
Каждый пакет состоит из заголовка и самих данных. Заголовок содержит служебную информацию, например порт источника и назначения.
Спецификация протокола TCP доступна здесь.
Протокол TCP и его особенности
Протокол TCP находится на 4 уровне модели OSI, если кто не знаком с этой моделью, то про неё я писал здесь.
Главной особенностью TCP (Transmission Control Protocol) является то, что этот протокол гарантирует доставку всех отправленных пакетов. При этом проверяется целостность пакетов и их порядок. Если пакет потерялся или испортился, то получатель запросит эти пакеты у отправителя снова. Если пакеты пришли не в том порядке, то они на принимающей стороне всё равно обработаются в правильном. Этот механизм контроля доставки накладывает дополнительную нагрузку в виде увеличения служебной информации, которую нужно передать вместе с полезными данными.
Протокол TCP делит поток информации на сегменты. В одном сегменте может быть несколько пакетов. Каждый сегмент проверяется на целостность, и если все хорошо, отправляется подтверждение передающей стороне. Таким образом подтверждается не каждый пакет, а каждый сегмент, но в сегменте может оказаться и всего лишь один пакет.
Поверх протокола TCP работают многие прикладные протоколы:
- сайты (http, https);
- электронная почта (imap, pop, smtp);
- передача файлов (cifs, nfs, ftp);
- удаленные подключения (rdp, ssh).
TCP пакеты передаются не просто так, а в рамках установленного соединения — которое называют TCP сессией.
Подключение можно выполнить только если вторая сторона прослушивает порт, к которому будет выполняться подключение.
И так, повторим особенности протокола TCP:
- Гарантия доставки;
- Установка соединения (сессии);
- Для подключения требуются порты.
Заголовок TCP пакета
Заголовок TCP занимает от 20 до 60 байтов (если используются опции), и состоит из полей.

- Source port (порт отправителя) и Destination port (порт получателя).
- Sequence number (порядковый номер в сегменте). Номер первого пакета в сеансе генерируется случайным образом, а следующие пакеты в сеансе, просто увеличивают свой порядковый номер.
- Acknowledgment number (номер подтверждения). Для подтверждения получения сегмента, в ответном пакете с флагом Ack записывается номер подтверждения, который на 1 больше последнего пакета из полученного сегмента. Например, был получен сегмент с пакетами 1-2-3-4-5. Получатель, для подтверждения, кидает пакет с флагом Ack и ack.number=6.
- Header Length (длина заголовка). Это поле необходимо, так как заголовок TCP может иметь разную длину из-за опций. И фактические данные могут начинаться в разных местах.
- Reserved. Зарезервированное поле для будущего использования.
- Code bits (флаги). Необходимы для дополнительной функциональности. Например, позволяют установить или разорвать соединение.
- Window (размер окна). Указывается количество байт, считая от последнего номера подтверждения, которые готов принять отправитель данного пакета. Я уже говорил что подтверждение идёт не на каждый пакет, так вот размер окна, это как-раз то, сколько пакетов можно отправить без подтверждения. Кстати, каждый пакет это 1460 байт.
- Checksum (контрольная сумма). Используется для проверки на наличие ошибок при приеме или передачи пакетов.
- Urgent (срочный). Используется, если стоит флаг URG. По этому значению определяются срочные данные и они сразу же передаются приложению. Сейчас это редко используется. Раньше применялось, например для протокола Telnet, чтобы по нажатию Ctrl+C оборвать сессию.
- Options (опции). Необязательно, но используются почти всегда. Например есть опция Windows scale, она применяется в 1Gb или 10Gb сетях. Если Windows scale=10, то за раз мы сможет отправить 146000 Байт (1Мбит). А за секунду будет ещё больше, в зависимости от задержки сети.
- Заполнение (Padding). Дополняет заголовок, пока он не закончится на 32-разрядной границе. Всегда состоит только из нулей.
Флаги TCP
Флаги отвечающие за перегрузку сети
Существует механизма явного уведомления о перегрузке сети ECN (Explicit Congestion Notification). Механизм ECN работает так:
- Роутер обнаруживает перегрузку и устанавливает флаг ECN в IP-заголовке.
- Получатель видит это и устанавливает ECE в TCP-заголовке.
- Отправитель получает ECE, снижает скорость передачи и отправляет CWR.
Этот механизм позволяет оптимизировать отправку пакетов в перегруженных сетях.
То есть для работы этого механизма используются флаги:
- ECE (ECN-Echo). Выполняет две функции. Если соединение только устанавливается, то означает что отправитель поддерживает ECN. В другом случае, это означает перегрузку сети для отправителя.
- CWR (Congestion Window Reduced). Подтверждение получения пакета с флагом ECE и включением механизма уменьшения перегрузки.
Флаги отвечающие за установку соединения
- SYN. Данный флаг означает начало соединения. Он также синхронизирует начальные номера. Первый пакет, отправленный с каждой стороны, должен иметь этот флаг.
- ACK. Устанавливается, когда принимающая сторона подтверждает полученный пакет. Чтобы отправитель знал, какие пакеты уже были доставлены получателю. При этом в поле acknowledgment number записывается номер подтверждаемого пакета+1.
- FIN. Сообщает другой стороне что все пакеты были отправлены, и соединение пора завершить.
- RST. Сообщает о немедленном разрыве соединения. При этом соединение обрывается, а буфер очищается. Самые распространенные причины отправки пакета с таким флагом:
- ответ на пакет, полученный для закрытого сокета;
- пользователь сам прервал соединение (например, закрыв браузер, не дожидаясь ответа);
- соединение не было нормально закрыто, но находится в неактивном состоянии некоторое время.
Остальные флаги
- PSH (Push). Как мы уже поняли, обычно получатель не подтверждает каждый пакет при получении. А данный флаг сообщает получателю, что нужно немедленно передать всё из буфера приложению и сразу же отправить подтверждение. Он часто используется в приложениях, где требуется немедленная обработка данных, таких как веб-браузеры, чаты и другие интерактивные приложения.
- URG (Urgent). Указатель важности. 0 если не используется, 1 — используется. В настоящее время мало где используется.
Создание сеанса TCP
Для того, чтобы создать сеанс связи используется трёхэтапное рукопожатие (TCP three-way handshake) между двумя узлами:
- Отправитель отправляет получателю пакет с флагом SYN, с помощью которого запрашивает установку соединения.
- Получатель отвечает пакетом с флагами SYN и ACK, с помощью которых подтверждает приём пакета от отправителя и тоже запрашивает установку соединения.
- Отправитель подтверждает что он получил пакеты от получателя с помощью пакета с флагом ACK.

При отправке пакеты последовательно нумеруются и рассчитывается их контрольная сумма. Поскольку все пакеты имеют последовательные номера, то становится видно если какие-то из них отсутствуют. В этом случае получатель отправляет запрос на повторную отправку пакетов.
Первый этап. Клиент отправляет на сервер пакет с флагом SYN. При этом клиент устанавливает порядковый номер сегмента на случайное значение, например seq. number=125.
Второй этап. В ответ сервер отвечает пакетом с флагами SYN и ACK. Номер подтверждения установлен на единицу больше принятого (ack. number=126). Поскольку сервер также будет отправлять данные, то для себя он тоже выбирает номер первого пакета, например seq. number=130.
Третий этап. Клиент отправляет ACK на сервер. Порядковый номер устанавливается равным seq. number=127, а номер подтверждения устанавливается на ack. number=131.
На этом этапе клиент и сервер получили подтверждение соединения и образовали двухстороннюю связь. В дальнейшем нумерация пакетов будет последовательно расти.
Признаком установленного TCP-соединения являются пакеты, не содержащие флагов SYN и ACK, но с корректными значениями полей Sequence Number и Acknowledgment Number.
Передача данных TCP
Теперь разберём пример передачи данных в уже установленном сеансе.

Клиент отравляет запрос к серверу. Поскольку данные поместились в один пакет TCP, то этот запрос (пакет) получил флаг PSH, чтобы сервер не ждал продолжение получения данных. При этом пакет получил 2 флага: ACK (подтвердил предыдущею передачу пакетов от сервера) и PSH.
В ответ на это сервер отправляет пакет ACK с номером успешно полученных данных.
Далее сервер обработал запрос и отправляет данные клиенту. Эти данные делятся на пакеты и отправляются сегментами.
Далее клиент подтверждает, что данные получены отправляя пакеты с флагом ACK, который имеет номер на 1 больше, чем номер последнего пакета из принятого сегмента.
Завершение сеанса TCP
Завершение сеанса использует четырёхэтапное рукопожатие, причём каждая сторона завершает своё соединение независимо.

Когда одна из сторон хочет остановить свою половину соединения, она передаёт пакет FIN, который другая сторона подтверждает пакетом с ACK.
После того, как сторона, отправившая первый FIN, ответила с последним ACK, она ожидает некоторое время прежде чем окончательно закрыть соединение. В течение этого времени локальный порт недоступен для новых соединений.
Соединение может быть «полуоткрытым», и в этом случае одна сторона завершила свою часть, а другая — нет. Завершившая сторона больше не может отправлять какие-либо данные, но другая сторона может. Завершающая сторона должна продолжить чтение данных, пока другая сторона также не завершит свою работу.
Также возможно разорвать соединение трёхэтапным рукопожатием, когда первая сторона отправляет FIN, а вторая отвечает FIN и ACK (просто объединяет 2 шага в один). Дальше первая сторона подтверждает завершение сеанса с помощью ACK.
Состояния сеанса TCP
Сеанс TCP может находится в следующих состояниях:
- CLOSED — начальное состояние;
- LISTEN — сервер ожидает запросы от клиента;
- SYN-SENT — клиент хочет установить соединение с сервером и ожидает подтверждение;
- SYN-RECEIVED — сервер получил запрос на создание сеанса, отправил ответный запрос и ожидает подтверждение;
- ESTABLISHED — соединение установлено, идёт передача данных;
- FIN-WAIT-1 — одна из сторон завершает соединение, отправив флаг FIN;
- CLOSE-WAIT — другая сторона переходит в это состояние, отправив подтверждение на FIN, но продолжает передачу;
- FIN-WAIT-2 — первый узел получил ACK, разорвал свое соединение, но еще читает данные;
- LAST-ACK — второй узел заканчивает передачу и отправляет флаг FIN;
- TIME-WAIT — сервер получил пакет с флагом FIN, отправил флаг ACK и ждёт некоторое время, перед окончательным закрытием соединения;
- CLOSING — обе стороны инициировали закрытие соединения одновременно.
Вот мы и познакомились с одним из самых важных протоколов сети Интернет. Протокол TCP действительно очень важен в компьютерных сетях. Разобрались с его особенностями, алгоритмом работы. Узнали про сеансы TCP, пакеты и сегменты.
Я также описывал ещё один важный протокол компьютерной сети, а именно протокол UDP. Статья доступна здесь.
Также, на тему TCP мне понравилось одно видео, оставлю ссылку на ного здесь.
Если понравилась статья, подпишись на мой канал в VK или Telegram.