Происходят ли повторные попытки отправить потерянный пакет при использовании UDP и TCP?

«Происходят ли повторные попытки отправить потерянный пакет при использовании UDP и TCP?» — вопрос из категории Сети, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

TCP — да, UDP — нет. Это фундаментальное различие в гарантиях доставки.

  • TCP (Transmission Control Protocol) — надежный, ориентированный на соединение протокол. Он использует механизмы подтверждения (ACK), таймауты и повторные передачи (retransmission) для гарантии доставки и порядка пакетов. Если отправитель не получает ACK в течение заданного времени, пакет отправляется заново.
  • UDP (User Datagram Protocol) — ненадежный, дейтаграммный протокол. Он не устанавливает соединение, не ожидает подтверждений и не выполняет повторных передач. Отправленный пакет может быть потерян, продублирован или прийти в неправильном порядке.

Пример на C++ с сокетами (упрощенно):

TCP-клиент (надежная отправка):

// После установки соединения (connect)
char buffer[] = "Hello TCP";
int bytes_sent = send(tcp_socket, buffer, strlen(buffer), 0);
// Ядро ОС/стек TCP позаботится о повторной отправке, если ACK не придет.

UDP-клиент («отправил и забыл»):

sockaddr_in server_addr = {/* ... */};
char buffer[] = "Hello UDP";
int bytes_sent = sendto(udp_socket, buffer, strlen(buffer), 0,
                       (const sockaddr*)&server_addr, sizeof(server_addr));
// Никаких повторных попыток. Данные могут быть потеряны.

Выбор протокола:

  • TCP: Веб-серверы (HTTP), передача файлов (FTP), удаленный доступ (SSH) — где важна целостность данных.
  • UDP: Стриминг видео/аудио (потеря пакета менее критична, чем задержка), DNS-запросы, онлайн-игры — где важна низкая задержка, а надежность реализуется на уровне приложения (если требуется).