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。嗯,丢包了。这时候接收端可以做什么?
- 直接丢弃: 如果 102 是 B 帧或 P 帧,丢了影响不大,解码器能扛过去。
- 请求重传: 通过 RTCP(RTP Control Protocol)的 NACK 包告诉发送端「102 丢了,重发一下」。
- 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 协议选择决策流程
说了这么多,到底该用哪个协议?我画了一张决策图,帮你快速判断:
这张图的核心逻辑很简单:网络好就用 TCP,网络差但可控就用 RTP 加 FEC,网络差且不可控就上 SRT。别想着一个协议打天下,不存在的。
最后提醒一句: 协议只是工具,不是银弹。我见过有人把 SRT 的延迟调到 1000ms 还说「这是低延迟」,那还不如直接用 TCP。理解每个协议的适用边界,比背参数重要得多。