TCP

Предпосылки: UDP (порт, сокет, датаграмма), IP и маршрутизация (пакет, TTL).

UDP | TCP Tuning

UDP передаёт данные без гарантий — быстро, но ненадёжно. Для загрузки файла, HTTP-запроса или подключения к базе данных потеря или перестановка байтов недопустима. Нужен протокол, который гарантирует: данные дойдут, дойдут в правильном порядке, не продублируются, и отправитель не перегрузит получателя.

Соединение

TCP (Transmission Control Protocol — протокол управления передачей) решает все четыре задачи. Фундаментальное отличие от UDP: TCP создаёт соединение (connection). UDP — как отправка открыток: каждая независима. TCP — как телефонный звонок: установка соединения, обмен данными, завершение. Соединение — это состояние, хранимое на обоих концах: номера последовательности, размеры буферов, таймеры.

Трёхстороннее рукопожатие

Handshake (рукопожатие) — процедура установки соединения:

sequenceDiagram
    participant C as Клиент
    participant S as Сервер
    C->>S: SYN (seq=X)
    S->>C: SYN-ACK (seq=Y, ack=X+1)
    C->>S: ACK (ack=Y+1)
    Note over C,S: Соединение установлено

SYN (synchronize) — “хочу соединиться, мой начальный номер X”. SYN-ACK — “принял, мой начальный номер Y”. ACK (acknowledge) — “принял”. Три шага нужны, чтобы обе стороны убедились, что связь работает в обе стороны: после двух шагов сервер не знает, дошёл ли его ответ до клиента.

В Linux эта абстракция доступна через системные вызовы socket(), connect(), listen() и accept() — подробнее в сокетах.

Сегмент

Сегмент (segment) — единица данных TCP. TCP “нарезает” поток данных на части. Ключевые поля заголовка (минимум 20 байт):

+----------------+----------------+-----------------+-----------------+
| Порт           | Порт           | Sequence Number | Acknowledgment  |
| отправителя    | получателя     | (номер послед.) | Number (подтв.) |
| (2 байта)      | (2 байта)      | (4 байта)       | (4 байта)       |
+----------------+----------------+-----------------+-----------------+
| Флаги (SYN, ACK, FIN, RST...), размер окна, контр. сумма...        |
+---------------------------------------------------------------------+
| Данные (payload)                                                    |
+---------------------------------------------------------------------+

Sequence Number и ACK: надёжность и порядок

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

Sequence Number — номер первого байта данных в сегменте. Сегмент 1: seq=1000, 500 байт — байты 1000–1499. Сегмент 2: seq=1500, 500 байт — байты 1500–1999. Если сегмент 2 придёт раньше, получатель положит его в буфер и подождёт сегмент 1.

Acknowledgment — подтверждение получения. Получатель отправляет ACK с номером: “получил всё до N, жду N и дальше”. Отправитель посылает байты 1000–1499, получатель отвечает ACK=1500. Отправитель посылает 1500–1999, получатель отвечает ACK=2000. Если ACK не приходит в течение таймаута — повторная передача (retransmission).

Таймаут вычисляется динамически на основе RTT (Round-Trip Time — время туда-обратно). Быстрая сеть — короче таймаут. Медленная — длиннее.

Управление потоком: окно

Отправитель может “завалить” получателя данными быстрее, чем тот обрабатывает. Управление потоком (flow control) решает это через окно (window): получатель в каждом ACK сообщает размер окна — “у меня W байт свободного места”. Отправитель не шлёт неподтверждённых данных больше, чем размер окна. Получатель перегружен — окно уменьшается вплоть до нуля.

Контроль перегрузки: адаптация к сети

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

Congestion control — адаптация к состоянию сети. Принцип: потеря пакетов = сигнал перегрузки, нужно замедлиться. Slow start: начать с маленького окна перегрузки (cwnd), увеличивать экспоненциально при успешной доставке. Congestion avoidance: после достижения порога — увеличивать линейно. При потере — резкое уменьшение окна.

Завершение соединения

Соединение полнодуплексное — каждая сторона завершает передачу независимо:

sequenceDiagram
    participant C as Клиент
    participant S as Сервер
    C->>S: FIN ("я закончил отправлять")
    S->>C: ACK ("понял")
    S->>C: FIN ("я тоже закончил")
    C->>S: ACK ("понял")

FIN (finish) — “больше не буду отправлять данные”. RST (reset) — грубое немедленное закрытие без церемоний.

Полная инкапсуляция

На этом этапе видна полная картина вложенности: данные приложения (например, HTTP) помещаются в TCP-сегмент, тот — в IP-пакет, а он — в Ethernet-кадр:

+---------------------------------------------------------------------+
| Ethernet-кадр                                                       |
| +------------------------------------------------------------------+|
| | MAC-заголовок | IP-пакет                                         ||
| |               | +----------------------------------------------+ ||
| |               | | IP-заголовок | TCP-сегмент                    | ||
| |               | |              | +----------------------------+ | ||
| |               | |              | | TCP-заголовок | Данные      | | ||
| |               | |              | |               | (HTTP)      | | ||
| |               | |              | +----------------------------+ | ||
| |               | +----------------------------------------------+ ||
| +------------------------------------------------------------------+|
+---------------------------------------------------------------------+

TCP vs UDP

ХарактеристикаTCPUDP
СоединениеДа (stateful)Нет (stateless)
НадёжностьГарантированаНе гарантирована
ПорядокСохраняетсяНе сохраняется
Накладные расходы20+ байт заголовка8 байт заголовка
ПрименениеHTTP, файлы, БДВидео, игры, DNS

TCP обеспечивает надёжный канал между приложениями. Но приложениям нужно ещё понимать друг друга — преобразовать имя сервера в IP-адрес (DNS), договориться о формате обмена (HTTP), защитить данные от перехвата (TLS).


UDP | TCP Tuning