3、传输协议与丢包:UDP vs TCP、RTP协议中的丢包处理、SRT协议简介

聊到流媒体的传输协议,很多人第一反应就是「TCP 可靠,UDP 不可靠」。这话没错,但在直播场景里,事情远没那么简单。我这些年踩过的坑,有一半都跟协议选择有关。今天咱们就把 UDP、TCP、RTP 和 SRT 这几个东西掰开揉碎了讲清楚。

3.1 UDP vs TCP:直播场景下的生死抉择

先问个问题:为什么直播行业普遍用 UDP 而不是 TCP?

你想想看,TCP 为了保证数据完整,搞了一套重传机制。丢一个包,它就等重传,重传不到就一直等。这在文件下载时是好事,但在直播里就是灾难——画面卡住不动,观众早就跑了。

UDP 呢?丢了就丢了,继续往下传。视频解码器有容错能力,丢几个包顶多花屏一下,总比卡死强。

核心差异对比:

特性 TCP UDP
可靠性 保证送达,顺序一致 尽力而为,不保证
延迟 高(重传导致) 低(无重传)
适合场景 点播、文件传输 直播、实时通信
丢包影响 卡顿、等待 花屏、跳帧
头部开销 20 字节 8 字节

我在做某大型体育赛事直播时,就遇到过 TCP 导致的严重问题。推流端用 TCP 连到边缘节点,网络抖动一下,整个推流链路就卡死了。后来换成 UDP + 应用层重传,问题才解决。

我的建议: 内网传输或网络极好的场景可以用 TCP,公网直播老老实实用 UDP。别跟物理规律对着干。

3.2 RTP 协议中的丢包处理机制

RTP(Real-time Transport Protocol)是 UDP 之上的「半可靠」协议。它不保证送达,但提供了丢包检测和恢复的基础能力。

3.2.1 RTP 头部中的关键字段

RTP 头部有 12 个字节的固定部分,其中跟丢包处理直接相关的有两个:

  • 序列号(Sequence Number): 16 位,每发一个包加 1。接收端靠它判断有没有丢包。
  • 时间戳(Timestamp): 32 位,用于同步和抖动计算。

举个例子:你收到了序列号 100、101、103 的包,中间缺了 102。嗯,丢包了。这时候接收端可以做什么?

  1. 直接丢弃: 如果 102 是 B 帧或 P 帧,丢了影响不大,解码器能扛过去。
  2. 请求重传: 通过 RTCP(RTP Control Protocol)的 NACK 包告诉发送端「102 丢了,重发一下」。
  3. FEC 恢复: 如果启用了前向纠错,可以用后续包把 102 算出来。

注意: 序列号只有 16 位,最大 65535。长时间直播会溢出,需要做回绕处理。我曾经见过一个项目没处理回绕,导致丢包检测完全失效,画面花得一塌糊涂。

3.2.2 RTCP 的 NACK 与 FIR

RTCP 是 RTP 的控制协议,负责反馈网络状态。两个关键报文:

  • NACK(Negative ACK): 告诉发送端「我丢了哪些包」,发送端选择性重传。
  • FIR(Full Intra Request): 请求一个完整的 I 帧。当丢包太多导致解码器崩溃时,用这个强制刷新。

我在实际项目中,一般把 NACK 的超时时间设在 50-100ms。太短了重传风暴,太长了延迟受不了。

3.2.3 FEC(前向纠错)

FEC 是另一种思路:发送端多传一些冗余数据,接收端即使丢了一部分也能恢复。常见的算法有 XOR 和 Reed-Solomon。

举个例子,每 4 个数据包生成 1 个冗余包:

数据包: P1 P2 P3 P4
冗余包: P1 XOR P2 XOR P3 XOR P4

如果丢了 P2,接收端可以这样恢复:
P2 = P1 XOR P3 XOR P4 XOR 冗余包

FEC 的代价是带宽增加。冗余率 20% 意味着多消耗 20% 的带宽。我一般建议在丢包率 5%-10% 的场景下开启 FEC,丢包率更高时配合重传一起用。

丢包恢复策略对比:

策略 延迟增加 带宽消耗 适用丢包率
直接丢弃 无 无 < 1%
NACK 重传 RTT 级别 按需 1%-5%
FEC 无 固定冗余 5%-10%
FEC + NACK 低 中等 10%-20%

3.3 SRT 协议简介

SRT(Secure Reliable Transport)是近年来非常火的一个协议。它本质上是在 UDP 之上实现了一个「类 TCP 的可靠传输」,但延迟远低于 TCP。

3.3.1 SRT 的核心思想

SRT 用了几招来平衡可靠性和延迟:

  • ARQ(自动重传请求): 丢包后选择性重传,但不像 TCP 那样阻塞后续数据。
  • 动态缓冲区: 根据网络抖动自动调整接收缓冲区大小。
  • 加密: 内置 AES 加密,省去了单独加 TLS 的麻烦。

说白了,SRT 想解决的是「公网传输既要低延迟又要高可靠」这个矛盾。我最近在做一个跨国直播项目,从北京推到洛杉矶,用 SRT 延迟控制在 300ms 以内,丢包率从 15% 降到了 0.5% 以下。

3.3.2 SRT 的参数调优

SRT 有几个关键参数需要根据网络状况调整:

参数 说明 推荐值
latency 接收端缓冲区延迟(ms) 120-500
rcvlatency 接收端等待重传的时间 latency 的 60%
peerlatency 对端缓冲区延迟 与 latency 一致
maxbw 最大带宽(bps) 码率的 1.5 倍

避坑指南: 我曾经把 latency 设得太小(50ms),结果网络一抖动就疯狂重传,带宽直接打满。后来改成 200ms,世界清净了。记住,SRT 的延迟参数不是越小越好,要跟网络 RTT 匹配。

3.4 协议选择决策流程

说了这么多,到底该用哪个协议?我画了一张决策图,帮你快速判断:

传输协议选择决策流程 传输协议选择决策流程 网络条件评估 丢包率 < 1% 且 RTT < 20ms? 是 TCP / RTMP 否 丢包率 1%-10% 且可控? 是 RTP + FEC + NACK 否 SRT / QUIC 说明 丢包率超过 20% 时,任何协议都救不了。先修网络,再谈优化。

这张图的核心逻辑很简单:网络好就用 TCP,网络差但可控就用 RTP 加 FEC,网络差且不可控就上 SRT。别想着一个协议打天下,不存在的。

最后提醒一句: 协议只是工具,不是银弹。我见过有人把 SRT 的延迟调到 1000ms 还说「这是低延迟」,那还不如直接用 TCP。理解每个协议的适用边界,比背参数重要得多。