Содержание статьи +
- TL;DR
- Зачем это понимать
- Что вообще делает транспортный протокол
- TCP в одном абзаце
- UDP в одном абзаце
- Head-of-line blocking – факт, который решает всё
- TCP против UDP – сравнительная таблица для команды
- Почему HLS и DASH прекрасно живут на TCP
- Почему WebRTC, SRT и RIST живут на UDP
- Числовой пример: один и тот же потерянный пакет по TCP и по UDP
- QUIC и Media over QUIC – новая карта
- Типичная ошибка – думать, что TCP «надёжнее» в каком-то полезном смысле
- Где здесь Фора Софт
- Ключевые выводы
- Что почитать дальше
Опубликовано: 2026-05-20 · Время чтения: 17 мин · Автор: Николай Сапунов, CEO Фора Софт
Последняя сверка: 2026-05-20 со стандартами: IETF RFC 793 (TCP, 1981), RFC 9293 (TCP, август 2022 – заменяет RFC 793), RFC 768 (UDP, 1980), RFC 9000 (QUIC, май 2021), RFC 8085 (UDP Usage Guidelines, март 2017), RFC 3550 (RTP, июль 2003), RFC 8216 (HLS, август 2017), Apple HLS Authoring Specification ревизия 2025-09, ISO/IEC 23009-1:2022 (DASH), draft-sharabayko-srt-01 (SRT, март 2024), SMPTE TR-06-1:2020 (RIST), RFC 8825 (обзор WebRTC, январь 2021) и RFC 9725 (WHIP, март 2025).
TL;DR
TCP – это транспортный протокол, который гарантирует, что каждый байт дойдёт, придёт в нужном порядке, переотправит потерянные пакеты и сам управляет окном получателя; идеально для загрузки веб-страницы и мучительно для цели в 100 мс live-задержки, потому что один потерянный пакет блокирует всё, что идёт после него. UDP – это минимально-возможный транспорт, который отправляет пакеты и забывает о них: быстрый, без упорядочивания, потери – это норма; ровно то, что нужно, если вы готовы построить восстановление потерь сами. Каждый стриминговый протокол выбирает один из этих двух фундаментов: HLS, DASH и CMAF живут на TCP, потому что они отдают файло-подобные сегменты по HTTP; WebRTC, SRT, RIST, RTP и Media over QUIC живут на UDP, потому что им нужен каждый кадр в момент его кодирования. Главная причина этого разделения – проблема head-of-line blocking, и после статьи вы сможете по названию любого стримингового протокола сразу сказать, на каком транспорте он сидит и почему.
Зачем это понимать
Вопрос «TCP или UDP» – первое архитектурное решение в любом стриминговом продукте, и оно распространяется на всё: оно ставит нижнюю планку задержке, которую вы вообще когда-нибудь увидите; решает, может ли CDN кэшировать ваш трафик; меняет, как вы работаете с файрволами и корпоративными сетями; и определяет, сколько денег вы тратите на TURN-трафик в WebRTC. Команда, не понимающая разницу, выберет неподходящий протокол для задачи – обычно HLS для real-time аукциона или WebRTC для концерта на 200 000 зрителей – и обнаружит ошибку через три месяца, когда архитектура перестанет тянуть. То же самое непонимание видно в RFP к вендорам, где просят «низкую задержку поверх HTTP», не признавая, что физика TCP кладёт пол под эту задержку. Эта статья даёт четыре факта, решающие вопрос для любого стримингового протокола, который вы когда-либо будете оценивать: что именно гарантирует каждый транспорт, под какие задачи подходит каждый, ловушку head-of-line blocking и то, как QUIC начинает стирать старую границу между TCP и UDP в 2026 году.
Что вообще делает транспортный протокол
Перед TCP и UDP – слой ниже. Internet Protocol (IP) передаёт пакет по адресу назначения и пожимает плечами: он не гарантирует ни доставку, ни порядок, ни целостность пакета. Транспортный протокол – это слой, который сидит поверх IP и решает, что со всем этим делать.
Каждый транспортный протокол отвечает на шесть вопросов о каждом байте, который вы ему передаёте: должен ли байт вообще дойти (надёжность), в каком порядке байты должны приходить (упорядочивание), как реагировать на перегрузку в сети (congestion control), как сказать отправителю «помедленнее», если получатель не справляется (flow control), как понять, какому приложению какой пакет (мультиплексирование по портам), и как зафиксировать, что две конечные точки правда разговаривают друг с другом (состояние соединения). TCP отвечает на все шесть. UDP отвечает ровно на один – мультиплексирование по портам – и оставляет остальные пять приложению.
Разница между «отвечает на шесть» и «отвечает на один» – это и есть вся суть.
TCP в одном абзаце
Transmission Control Protocol, определённый в IETF RFC 793 (сентябрь 1981) и модернизированный в RFC 9293 (август 2022, формально заменяющем RFC 793), – это соединение-ориентированный, надёжный, упорядоченный байт-стрим-транспорт. До начала передачи данных конечные точки обмениваются тремя сообщениями (SYN, SYN-ACK, ACK), чтобы согласовать, что они соединены, и синхронизировать начальные sequence-номера – это three-way handshake. После установления соединения отправитель передаёт TCP поток байт; TCP режет его на сегменты, нумерует каждый байт, кладёт в IP-пакеты и ждёт, пока получатель подтвердит (ACK) каждый непрерывный диапазон. Если ACK не пришёл в течение рассчитанного retransmission timeout, TCP переотправляет. Получатель отдаёт байты приложению строго по порядку – даже если байт 1000 пришёл раньше байта 500, приложение не увидит ничего до прихода 500-го. TCP также крутит алгоритм congestion control (в 2026 деплоятся CUBIC, BBR и Reno), который зондирует доступную пропускную способность и сужает окно отправителя при потерях. Результат с точки зрения приложения – идеальная упорядоченная труба: каждый отправленный байт приходит один раз, по порядку, в конце концов.
«В конце концов» – это место, где стримингу становится больно.
UDP в одном абзаце
User Datagram Protocol, определённый в IETF RFC 768 (август 1980), – это connectionless, ненадёжный, message-oriented транспорт. Никакого handshake нет: вы передаёте UDP датаграмму (одно сообщение размером до 65 507 байт после IP- и UDP-заголовков), он прикручивает 8-байтовый UDP-заголовок, отдаёт IP и уходит. Нет ACK, переотправки, упорядочивания, congestion control и flow control. Если датаграмма потеряна, вы об этом от UDP не узнаете – приложение должно само заметить потерю и решить, что делать. Если две датаграммы пришли в обратном порядке, они так и пришли. Если сеть забита и получатель тонет, UDP будет жарить с прежней скоростью. UDP даёт приложению четыре вещи: порт назначения, порт источника, длину и контрольную сумму. Всё остальное – забота приложения. RFC 8085 (UDP Usage Guidelines, март 2017) – длинный документ, единственная цель которого – объяснить разработчикам приложений, что TCP делает «бесплатно» и как построить это поверх UDP, не уронив сеть.
Звучит как катастрофа для видео. Для видео это, на самом деле, идеально – если понять, что такое head-of-line blocking.
Head-of-line blocking – факт, который решает всё
Если из этой статьи вы прочитаете только один абзац – прочитайте этот. TCP передаёт байты приложению строго по порядку. Эта гарантия реализована буферизацией. Когда TCP получил байты 1–499 и 501–1000, но не получил байт 500, он не отдаст приложению ничего, пока не придёт байт 500 – он держит байты 501–1000 в буфере ядра и ждёт переотправки. Приложение в это время ничего не видит. Эта задержка называется head-of-line blocking (блокировка головы очереди). Это фундаментальное свойство TCP, и выключить его нельзя.
Для веб-страницы head-of-line blocking – не событие. Приложение всё равно хочет каждый байт, а задержка в 200 мс на переотправку незаметна на фоне 2-секундного time-to-first-paint типичной страницы. Для видео с 5-секундным запасом задержки head-of-line blocking тоже терпим – у плеера буфер на несколько секунд, переотправка укладывается внутрь буфера.
Для видео с целью «менее секунды» head-of-line blocking – это вся проблема. Возьмём видеоконференцию на 30 кадрах в секунду: каждый кадр длится 33 мс. Если один пакет с частью кадра 100 потерян в сети, TCP не отдаст получателю кадр 101, 102, 103 и ничего после них, пока не переотправится кадр 100. Типичная переотправка по трансконтинентальному линку – 80–200 мс – три-шесть кадров заморожены ради одного. Получатель замирает на десятую долю секунды и потом «оживает» с идеально упорядоченной последовательностью кадров, которыми уже нельзя пользоваться, потому что разговор ушёл вперёд.
UDP просто отдаёт кадр 101 в момент его прихода, даже если кадр 100 пропал. Видео-конвейер говорит «я потерял пакет кадра 100, я его прикрою интерполяцией с кадра 99, ближайший I-frame полностью пересинхронизирует картинку максимум за 2 секунды» – и продолжает играть. Скрытие потерь декодером гораздо менее заметно, чем заморозка.
Именно поэтому каждый real-time стриминговый протокол сидит на UDP. Задача протокола – сделать UDP менее плохим, добавить правильный вид восстановления потерь – такой, который не блокирует голову очереди.
TCP против UDP – сравнительная таблица для команды
Шесть измерений, две колонки. Запомните таблицу – почти любой спор о выборе стримингового протокола укладывается в неё.
| Измерение | TCP | UDP |
|---|---|---|
| Установка соединения | 3-way handshake (1 RTT), плюс TLS-handshake сверху (ещё 1–2 RTT) | Нет. Первая датаграмма уже несёт первый байт полезной нагрузки. |
| Надёжность | Гарантия через ACK + переотправку | Best-effort. Потерями занимается приложение. |
| Упорядочивание | Строго по порядку (head-of-line blocking) | Нет. Датаграммы могут прийти в любом порядке. |
| Congestion control | Обязателен. CUBIC, BBR, Reno в 2026. | Нет. Должно реализовать приложение (RFC 8085). |
| Flow control | Receive window предотвращает переполнение получателя | Нет. Это забота приложения. |
| Заголовок | Минимум 20 байт (часто 32+ с опциями) | 8 байт |
| Пол задержки при потерях | 1 RTT на каждый потерянный пакет, блокирует поток | 0 – следующий пакет сразу попадает в приложение |
| Типичное применение в стриминге | HLS, DASH, RTMP-доставка (легаси), загрузка файлов | WebRTC, SRT, RIST, RTP, MoQ поверх QUIC |
Измерение, которое определяет архитектуру стриминга, – предпоследнее: пол задержки при потерях. На сети с потерями даже 1% эффективная пропускная способность TCP падает на порядок из-за стопоров на переотправках – формула Mathis и др. 1997 года, до сих пор служащая прикидкой на обратной стороне конверта, даёт throughput ≤ MSS / (RTT × √loss). Подставим MSS = 1460 байт, RTT = 80 мс, потери = 1%: предел – около 1,8 Мбит/с. Этого недостаточно для 1080p. UDP с собственным восстановлением потерь приложением такую формулу игнорирует.
Почему HLS и DASH прекрасно живут на TCP
Если TCP так плох для низкой задержки, почему два самых популярных стриминговых протокола на Земле – HTTP Live Streaming и Dynamic Adaptive Streaming over HTTP – оба сидят на TCP?
Ответ: HLS и DASH – не real-time протоколы. Они файло-подобные. Энкодер режет live-поток на сегменты по 2–10 секунд, пишет их как файлы (.ts, .mp4 или .m4s) в origin и даёт плееру тянуть их по обычному HTTP. HTTP едет по TCP. Плеер держит буфер обычно из 3–4 сегментов – при 6-секундных сегментах это 18–24 секунды буфера. Стопор переотправки в 200 мс внутри такого буфера невидим.
Этот буфер – ровно та задержка, которую вы платите за надёжность TCP и кэшируемость HTTP. Буфер – это то, что позволяет CDN кэшировать каждый сегмент, отдавать его с edge и обслуживать миллион одновременных зрителей, не плавя origin. Без буфера CDN не может кэшировать; без кэширования вы не масштабируетесь; без масштаба нет OTT.
Low-Latency HLS и Low-Latency DASH опускают буфер ниже, публикуя частичные сегменты по 200–400 мс – Apple HLS Authoring Specification (ревизия 2025-09, §2.10 и далее) подробно описывает LL-HLS-расширения. Результат – sub-3-секундная задержка glass-to-glass на хорошо настроенной выдаче, всё ещё на TCP. Ниже 3 секунд TCP начинает проседать; ниже 1 секунды TCP и UDP резко расходятся.
Вывод не «TCP плох для стриминга». Вывод – «TCP плох для стриминга с задержкой меньше 3 секунд». Для VOD на 5 секунд и live OTT TCP – правильный выбор: его надёжность и кэшируемость HTTP перевешивают плату за задержку. Для интерактивного видео класса 100 мс TCP бюджет не вытягивает.
Почему WebRTC, SRT и RIST живут на UDP
Три больших семейства real-time протоколов сидят на UDP и каждое реализует свою вариацию «сделаем UDP менее плохим».
WebRTC (W3C Recommendation плюс RFC 8825–8866 и семейство RTP, начиная с RFC 3550) переносит медиа в виде RTP-пакетов по UDP. У каждого RTP-пакета есть sequence-номер и timestamp. Получатель использует sequence-номер для обнаружения потерь и timestamp для расписания воспроизведения. При обнаружении потери WebRTC имеет несколько механизмов восстановления – NACK (отрицательное подтверждение конкретных потерянных пакетов), RTX (переотправка как отдельный RTP-поток с другим payload type), FEC (forward error correction – заранее добавляемая избыточность) и собственное скрытие ошибки кодеком. Ни один из них не блокирует голову очереди; если кадр 100 невозможно вовремя восстановить, декодер прикрывает его и играет 101. Glass-to-glass задержка в WebRTC обычно 100–500 мс.
SRT (Secure Reliable Transport, определённый в Internet-Draft draft-sharabayko-srt-01, март 2024 – обратите внимание на статус draft; SRT может измениться до выхода в RFC) оборачивает UDP смесью настраиваемого ARQ-переотправления, опционального FEC, AES-шифрования и доставки по timestamps. Хитрая часть – настраиваемый буфер задержки: вы говорите SRT «дай мне 200 мс jitter-буфера», и он использует этот бюджет, чтобы восстанавливать потери переотправкой, если round-trip укладывается, и сдавался, если нет. SRT – де-факто стандарт для профессиональных контрибуционных линков по публичному интернету (камера → энкодер → облако). Поведение по HoL настраивается: внутри бюджета SRT ждёт и переотправляет, за пределами – дропает и идёт дальше.
RIST (Reliable Internet Stream Transport, SMPTE TR-06-1, TR-06-2, TR-06-3) – ответ бродкаст-индустрии на ту же задачу. RIST сидит на UDP, несёт RTP, со своей схемой NACK-переотправки по RTP sequence-номерам. SRT двигали Haivision и Wowza, RIST двигали Video Services Forum и коалиция бродкаст-вендоров. Оба решают одну задачу с разной управленческой моделью.
RTMP и его потомки – единственное крупное исключение в контрибуционном семействе: RTMP едет по TCP, потому что был придуман в 1996 году, чтобы делить TCP-сокет с другим трафиком Flash. RTMP умирает как контрибуционный протокол; SRT и WHIP отъедают его долю именно потому, что TCP – неподходящий выбор для контрибуционной линии с любыми ощутимыми потерями.
Числовой пример: один и тот же потерянный пакет по TCP и по UDP
Подставим числа. Камера кодирует 1080p на 30 fps со средним кадром 8 КБ и пиковым I-frame 80 КБ. Линк до облака – 80 мс в одну сторону, 160 мс RTT, средняя потеря пакетов 0,5%. Один кадр уходит десятью UDP-датаграммами по 1500 байт (реальные числа – MTU 1500 минус IP- и UDP-заголовки).
На TCP (контрибуция через RTMP, легаси-случай): энкодер пушит десять пакетов в TCP-сокет. Один теряется. Ядро получателя буферизует девять. Энкодер узнаёт о потере, не дождавшись ACK в течение retransmission timeout (база 160 мс плюс jitter), и переотправляет пропавший. Получатель ждёт 160 мс до того, как любой из десяти пакетов станет доступен приложению. При 30 fps это 4,8 кадра стопора. Дальше приходит следующий кадр, по дороге снова теряется один пакет – ещё 160 мс стопора. При 0,5% потерь на десять пакетов на кадр ожидаемое число событий – один раз в двадцать кадров, или раз в 0,67 секунды. Пользователь видит явные заморозки и скачки каждые две трети секунды.
На UDP (контрибуция через WebRTC или SRT): тот же энкодер пакетизует те же десять датаграмм и выстреливает. Один теряется. Получатель берёт девять, замечает пропуск по RTP sequence-номеру, NACK-ает пропавший. NACK и переотправка занимают те же 160 мс, что и в TCP, но за это время декодер получает девять имеющихся пакетов, прикрывает пропавшую область данными предыдущего кадра и играет кадр в нужное время. Если переотправка пришла вовремя – её вкручивают; если нет – потеря закрыта, следующий кадр играется нормально. Видимой заморозки нет. Ближайший I-frame полностью пересинхронизирует картинку за 2 секунды.
Это и есть весь инженерный аргумент за UDP в интерактивном стриминге. Та же сеть, тот же процент потерь, тот же RTT – совершенно разный пользовательский опыт.
QUIC и Media over QUIC – новая карта
Дихотомия TCP-vs-UDP начинает стираться в 2026 году благодаря QUIC.
QUIC, определённый в IETF RFC 9000 (май 2021), – это транспортный протокол, который работает поверх UDP, но переотделывает почти всё, что делает TCP: надёжность, упорядочивание, congestion control, flow control и шифрование (TLS 1.3 зашит в handshake, а не прикручен сверху). Ядро видит UDP-датаграммы; приложение видит упорядоченный, надёжный, шифрованный байтовый поток. С точки зрения приложения QUIC очень похож на TCP + TLS.
Ключевое отличие – QUIC поддерживает множество независимых стримов в одном соединении, и потеря пакета в одном стриме не блокирует другие. В TCP каждый байт – в одном огромном упорядоченном потоке; head-of-line blocking распространяется на всё соединение. В QUIC можно иметь стрим 0 (видеочанк 1), стрим 1 (видеочанк 2), стрим 2 (аудиочанк 1), стрим 3 (субтитры) в полёте одновременно, и потеря на стриме 0 не задержит стримы 1, 2 и 3. Блокировка головы становится per-stream, а не per-connection. Для chunked-encoded HTTP/3-доставки CMAF-сегментов это ровно лекарство от пола задержки LL-HLS-on-TCP.
HTTP/3 (RFC 9114) – это HTTP поверх QUIC. HLS и DASH, доставляемые по HTTP/3, наследуют per-stream-изоляцию QUIC без изменений в протоколах выше. Media over QUIC, draft-ietf-moq-transport-17 (январь 2026; это Internet-Draft и может измениться до выхода в RFC), идёт дальше – он трактует поток как дерево именованных объектов, а не как список сегментов, с первоклассной поддержкой relay, multi-CDN и live-дистрибьюции с задержкой меньше секунды. MoQ – самый правдоподобный кандидат на «следующий дефолт» доставки после LL-HLS. Подробно – в Media over QUIC в деталях.
Практический вывод для 2026: TCP-vs-UDP – всё ещё правильная ментальная модель для понимания любого существующего протокола, но когда вы строите новый, тянитесь к QUIC. Cloudflare, Meta, Google и YouTube уже отдают значительные доли трафика по HTTP/3 в 2026, и доля QUIC в общем интернет-трафике перешагнула 30% в 2025 по отчёту Sandvine Global Internet Phenomena.
Типичная ошибка – думать, что TCP «надёжнее» в каком-то полезном смысле
Распространённая путаница продуктовых команд: «нам нужен надёжный стриминг, давайте TCP». Здесь смешивают два разных смысла слова надёжность.
Надёжность TCP – байт-уровня: каждый отправленный байт дойдёт, по порядку, в конце концов. Это свойство байтового потока, а не пользовательского опыта. С точки зрения зрителя замёрзшее видео не «надёжно» – оно сломано. Per-packet ненадёжность UDP в сочетании с возможностью реального приложения сбросить, замаскировать и пойти дальше даёт гораздо более полезную надёжность на уровне UX: картинка не останавливается.
Правильный вопрос не «TCP или UDP – что надёжнее», а «что мой продукт считает “пришло вовремя”». Для 24-секундного OTT-буфера «в конце концов» TCP – это вовремя. Для 100-миллисекундного конференц-бюджета всё, что не пришло за 100 мс, уже потеряно – и переотправка TCP в бюджет не укладывается, так что её «надёжность» не работает.
Считайте надёжность бюджетом, а не свойством. UDP плюс собственное восстановление потерь надёжнее внутри тугого бюджета задержки, чем TCP. TCP надёжнее вне любого бюджета. Выбирайте под бюджет.
Где здесь Фора Софт
Мы делаем видеостриминг, видеоконференции, OTT, видеонаблюдение, телемедицину, e-learning и AR/VR-продукты с 2005 года, и решение TCP/UDP – первый эскиз на каждой архитектурной доске. Телемедицинским консультациям нужен 200-миллисекундный WebRTC по UDP; e-learning-лекциям, записываемым для последующего просмотра, прекрасно подходит HLS по TCP; OTT live linear требует LL-HLS partial-segments на TCP с HTTP/3 там, где плеер его поддерживает; ингесту с камер в системах видеонаблюдения нужен SRT по UDP, потому что сотовая аплинк-линия теряет пакеты. Один и тот же конвейер часто несёт трафик по обоим транспортам на разных этапах – WebRTC-ингест с камеры по UDP, перекодирование и переупаковка в HLS по TCP для длинного хвоста зрительской аудитории. Знать, какой транспорт лежит под каждым хопом, – первая проверка здравого смысла, которую мы делаем, когда существующая система кажется медленной.
Ключевые выводы
- TCP отдаёт каждый байт по порядку с обязательной переотправкой; head-of-line blocking – это плата.
- UDP отдаёт каждую датаграмму независимо; восстановление потерь – задача приложения и в этом весь смысл для real-time видео.
- HLS, DASH и RTMP-доставка живут на TCP, потому что они файло-подобны и терпят буферизацию.
- WebRTC, SRT, RIST, RTP и MoQ живут на UDP, потому что им нужен каждый кадр сразу.
- Надёжность – это бюджет задержки, а не свойство; UDP плюс восстановление на уровне приложения надёжнее в узком бюджете.
- QUIC растворяет старую дихотомию: per-stream-мультиплексирование убивает блокировку головы очереди на уровне соединения.
Что почитать дальше
- Управление перегрузкой простыми словами: BBR, CUBIC, Copa – что алгоритм над транспортом делает с вашей пропускной способностью на загруженном линке.
- QUIC: новый транспортный уровень – подробный разбор протокола, переотделывающего TCP поверх UDP, и его роль как фундамента HTTP/3 и MoQ.
- Задержка, glass-to-glass, end-to-end: что означают эти секунды – статья Блока 1, формирующая каждый бюджет задержки против выбора TCP/UDP.