Получить доступ

Как TCP обеспечивает надёжную доставку и не перегружает сеть?

MiddleСети
Ещё спрашивают так:
  • Что такое окно TCP?
  • Как работает slow start?
  • Чем flow control отличается от congestion control?
Коротко

Каждый байт пронумерован, получатель подтверждает принятое (ACK), неподтверждённое отправляется повторно — по таймауту или по трём повторным ACK.

  • Flow control: окно получателя — сколько он готов принять
  • Congestion control: окно перегрузки — сколько сеть, по оценке отправителя, выдержит
  • Slow start удваивает окно каждый RTT до первой потери, дальше рост линейный

А ещё Пропускная способность одного соединения ≈ окно / RTT

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Попробуйте сами

TCP: рукопожатие, потери и повторная передача

Подробно

Подтверждения и повторы. Отправитель нумерует байты, получатель шлёт ACK с номером следующего ожидаемого байта (кумулятивное подтверждение; SACK позволяет сообщить и о кусках после дыры). Если ACK не пришёл за время RTO (оценивается по измеренному RTT), сегмент отправляется снова. Быстрее — fast retransmit: три одинаковых ACK значат, что сегмент потерялся, а следующие дошли.

Окно. Ждать ACK на каждый сегмент было бы медленно, поэтому отправитель держит «в полёте» до окна байт без подтверждения. Окно — минимум из двух:

  • окно получателя (rwnd) — свободное место в его буфере; приходит в каждом ACK. Это flow control: медленный читатель уменьшает окно до нуля, и отправитель останавливается. Пример backpressure прямо в протоколе;
  • окно перегрузки (cwnd) — оценка отправителя, сколько выдержит сеть. Это congestion control.

Как растёт cwnd (классический Reno/CUBIC):

  • slow start — начинаем с ~10 сегментов и удваиваем окно каждый RTT, пока не случится потеря или не дойдём до порога;
  • избегание перегрузки — дальше рост медленный (линейный у Reno, кубическая функция у CUBIC — по умолчанию в Linux);
  • потеря считается сигналом перегрузки: окно уменьшается (вдвое при тройном ACK, до минимума при таймауте).

BBR (Google) не ждёт потерь, а измеряет пропускную способность и минимальный RTT канала и держит в полёте их произведение. Лучше работает на каналах с потерями не от перегрузки (мобильные, дальние линии).

Следствия для практики:

  • скорость одного соединения ограничена ≈ окно / RTT — на дальних линиях с большим RTT нужно большое окно (масштабирование окна в заголовке);
  • новое соединение стартует медленно — ещё одна причина держать соединения открытыми (keep-alive, пулы);
  • потеря пакета тормозит весь поток — блокировка начала очереди, от которой уходит QUIC;
  • алгоритм Нейгла копит мелкие записи; для интерактивных протоколов его отключают TCP_NODELAY.

Пример

RTT = 50 мс, окно = 64 КБ:   64 КБ / 0,05 с ≈ 1,3 МБ/с ≈ 10 Мбит/с — даже на гигабитном канале
окно = 4 МБ:                 4 МБ / 0,05 с = 80 МБ/с ≈ 640 Мбит/с

Что хотят услышать

  • Нумерация, ACK, повтор по таймауту и по тройному ACK.
  • Окно и разница flow control и congestion control.
  • Slow start и реакция на потерю.
  • Связь окна, RTT и скорости; BBR — плюс.

Частые ошибки

  • Путать окно получателя и окно перегрузки.
  • Считать, что slow start — «медленный» рост; он экспоненциальный.

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем