Как TCP управляет потоком и перегрузкой?
Модели OSI и TCP/IP
Управление потоком защищает получателя (окно rwnd, которое он объявляет сам), управление перегрузкой — сеть (окно cwnd, которое отправитель оценивает по потерям); в полёте может быть не больше min(rwnd, cwnd) неподтверждённых байт.
Скользящее окно
- В каждом ACK получатель сообщает, сколько байт готов принять; с опцией window scaling окно растёт до ~1 ГБ.
- Отправитель держит в полёте не больше окна, по мере подтверждений окно сдвигается вперёд.
- Окно 0 — отправитель замирает и периодически шлёт window probe.
Перегрузка
- Slow start: cwnd стартует с 10 сегментов (IW10, RFC 6928) и удваивается каждый RTT.
- После порога ssthresh — congestion avoidance: рост примерно на 1 MSS за RTT.
- Три дублирующих ACK — fast retransmit, cwnd уменьшается вдвое (схема AIMD). Таймаут RTO — cwnd сбрасывается к минимуму, снова slow start.
Практика
- В Linux по умолчанию CUBIC; BBR от Google оценивает полосу и RTT, а не потери, и лучше работает на каналах со случайными потерями.
- Из-за IW10 в первый RTT уходит ~14 КБ, поэтому критичный HTML стараются уложить в этот объём.
- Пропускная способность одного потока ограничена величиной окно / RTT.
Коротко для собеседования
Отправитель ограничен сразу двумя окнами: тем, что объявил получатель, и тем, что он сам оценил для сети. Отсюда практическое следствие: скорость одного потока не выше окно / RTT, так что на дальних каналах выручают window scaling и BBR, а не ширина канала.