← Назад к вопросам

Как контролируется надежность соединения в TCP?

2.0 Middle🔥 191 комментариев
#Сети и протоколы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Механизмы контроля надёжности соединения в TCP

Основная идея

TCP (Transmission Control Protocol) обеспечивает надёжную доставку данных благодаря комплексу механизмов, которые гарантируют:
  • Все пакеты доходят до адресата
  • В правильном порядке
  • Без дублирования
  • Без повреждения данных

1. Порядковые номера (Sequence Numbers)

Каждый байт данных в TCP имеет уникальный порядковый номер:

// TCP заголовок
struct tcp_header {
    uint16_t src_port;
    uint16_t dst_port;
    uint32_t seq_number;     // Порядковый номер этого пакета
    uint32_t ack_number;     // Подтверждение получения данных
    uint8_t flags;           // SYN, ACK, FIN, RST и т.д.
    uint16_t window_size;    // Размер окна приёмника
    // ...
};

Функция: если пакет приходит не в порядке, TCP может переупорядочить данные или запросить повторную отправку

2. Подтверждение получения (ACK - Acknowledgment)

Приёмник отправляет обратно подтверждение:

Отправитель              Приёмник
--------- SEQ=1000 ----->
          DATA: 1000 байт
<-------- ACK=2000 -------
Получено до порядкового номера 2000

Механизм:

  • Приёмник отправляет ACK с номером, равным SEQ+длина_данных
  • Если отправитель не получает ACK за определённое время, переотправляет данные
  • Используется Retransmission Timeout (RTO), который адаптивно вычисляется

3. Контрольная сумма (Checksum)

Каждый TCP пакет содержит контрольную сумму:

// Вычисление контрольной суммы
uint16_t tcp_checksum(tcp_header* hdr, void* data, int len) {
    uint32_t sum = 0;
    
    // Суммируем все 16-битные слова
    uint16_t* words = (uint16_t*)hdr;
    for (int i = 0; i < sizeof(*hdr) / 2; i++) {
        sum += words[i];
    }
    
    words = (uint16_t*)data;
    for (int i = 0; i < len / 2; i++) {
        sum += words[i];
    }
    
    // Переполнение переносится в младшие биты
    sum = (sum & 0xFFFF) + (sum >> 16);
    sum = (sum & 0xFFFF) + (sum >> 16);
    
    return ~sum;
}

Если контрольная сумма не совпадает: пакет считается повреждённым и отбрасывается

4. Скользящее окно (Sliding Window)

ТCP использует окно размером в несколько КБ:

Отправитель может отправить до N байт
без ожидания ACK на каждый пакет

    [Отправлено]  [Ожидание ACK]  [Может быть отправлено]
    |-----------|---|------------|-----|
    0           100 200          900   1200
            (размер окна приёмника = 1200 - 200 = 1000 байт)

Преимущества:

  • Увеличивает пропускную способность
  • Уменьшает задержку (не ждём ACK на каждый пакет)
  • Динамический размер окна для адаптации к сети

5. Повторная отправка пакетов (Retransmission)

Если ACK не пришёл за время RTO:

// Псевдокод
while (packet_not_acked) {
    send_packet();
    wait_for_ack(rto_timeout);
    
    if (!ack_received) {
        rto *= 2;  // Экспоненциальная задержка
        // Повторить отправку
    } else {
        rto = recalculate_rto();  // Пересчитать RTO
        break;
    }
}

RTO вычисляется на основе:

  • Round-Trip Time (RTT) — время в оба конца
  • Вариативность RTT
  • Обычно: RTO = RTT + 4 * Deviation

6. Обнаружение потерь пакетов

Три способа обнаружить потерю:

a) Timeout (Timeout-based retransmission)

Просто ждём ACK, и если не пришёл — переотправляем

b) Duplicate ACKs (Fast Retransmit)

Получены пакеты: SEQ 1000, 2000, потеря, 4000
Приёмник отправляет три раза ACK на 2000
"ещё не получил пакет с SEQ 2000"

Отправитель видит 3+ одинаковых ACK
и сразу переотправляет без ожидания timeout

c) SACK (Selective Acknowledgment)

Приёмник отправляет информацию о том,
какие блоки он УСПЕШНО получил
и какие потеряны
Отправитель может переотправить только потеряные

7. Управление потоком (Flow Control)

Приёмник может сказать отправителю: «Медленнее!»

// В TCP заголовке
Window = 65535;  // Приёмник может принять столько байт

Если буфер приёмника переполняется, он отправляет Window = 0, и отправитель ждёт

8. Контроль перегрузки (Congestion Control)

ТCP адаптируется к нагрузке в сети:

  • Slow Start: экспоненциальное увеличение скорости передачи
  • Congestion Avoidance: линейное увеличение
  • Fast Recovery: быстрое восстановление после потери

Алгоритмы: Reno, Cubic, BIC

Пример: гарантия доставки в коде

// Создание TCP сокета
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sock, ...);

// TCP гарантирует, что данные доходят
// даже если отправим несколько раз
send(sock, data, len, 0);  // Переотправит при необходимости

// На приёмке — получим все данные в порядке
char buffer[1024];
recv(sock, buffer, sizeof(buffer), 0);
// Данные в buffer гарантированно в правильном порядке

Итого

Надёжность TCP обеспечивается комбинацией:

  • Порядковых номеров и ACK
  • Контрольных сумм
  • Механизма повторной отправки
  • Скользящего окна
  • Обнаружения потерь (timeout, fast retransmit, SACK)
  • Управления потоком и перегрузкой

Это делает TCP идеальным для приложений, где критична надёжность (HTTP, SMTP, SSH)

Как контролируется надежность соединения в TCP? | PrepBro