4. 网络传输优化:TCP/UDP模式选择、MTU分片策略、NAT穿透与防火墙配置

网络传输这块,说白了就是RTSP流能不能稳定到达客户端的关键。我见过太多项目,编码器参数调得再好,网络一抖全白费。今天咱们就把TCP/UDP怎么选、MTU怎么调、NAT和防火墙怎么绕,一次性说清楚。

核心观点:没有绝对最优的传输模式,只有最适合当前网络环境的策略。你的任务就是根据场景做选择题。

4.1 TCP vs UDP:不是二选一,是看场景

很多人一上来就问“RTSP到底用TCP还是UDP?”我的回答是:先搞清楚你的流要过什么网络。

对比维度 TCP UDP
可靠性 有重传,数据完整 无重传,可能丢包
延迟 较高(ACK等待) 低(无确认机制)
防火墙友好度 高(常见端口易放行) 低(端口随机,易被拦截)
适用场景 公网、跨运营商、弱网 局域网、低延迟监控

我个人习惯是:控制信令走TCP,媒体数据按需切换。RTSP本身支持transport头里指定模式,比如:

Transport: RTP/AVP/TCP;unicast;interleaved=0-1
Transport: RTP/AVP/UDP;unicast;client_port=5000-5001

我在项目中遇到过一个问题:某安防项目用UDP推流,跨省传输时画面频繁花屏。后来抓包发现中间路由器做了UDP限速,丢包率高达15%。切到TCP后,虽然延迟从80ms升到200ms,但画面完全正常了。嗯,这里要注意:UDP丢包超过5%时,视频质量会断崖式下降。

实战技巧:在推流客户端加一个自动探测逻辑——先尝试UDP,如果3秒内丢包率超过10%,自动回退到TCP。我写过类似逻辑,效果不错。

4.2 MTU分片策略:别让大包卡住你的流

MTU(最大传输单元)是网络设备的硬限制。以太网默认1500字节,但加上IP头和UDP头后,实际可用载荷只有1472字节(UDP)或1460字节(TCP)。

为什么会出问题?你想想看,如果RTP包封装后超过MTU,路由器就得做IP分片。分片后的包只要丢一片,整个包就废了。我见过最夸张的情况:一个1080p的RTP包被切成6片,丢一片就导致整帧花掉。

我的建议:主动控制RTP包大小,别让路由器替你分片。

// 伪代码:控制RTP包不超过MTU
#define MAX_RTP_PAYLOAD 1400  // 留余量,避免IP头扩展

void send_rtp_packet(uint8_t* data, int len) {
    int offset = 0;
    while (offset < len) {
        int chunk = min(MAX_RTP_PAYLOAD, len - offset);
        // 构造RTP头 + chunk
        send(chunk);
        offset += chunk;
    }
}

这里有个坑:不要简单地把MTU设为1500。因为PPPoE拨号会额外占8字节,VPN隧道可能占更多。我曾经在某个酒店网络里排查了三天,最后发现是PPPoE的MTU只有1492,而我的包是1500,导致所有大包都被丢弃。

避坑指南:我曾经在部署时忽略了这个细节,结果客户现场所有摄像头都连不上。后来加了一个MTU探测步骤——发一个带DF标志的大包,如果收到ICMP“需要分片”消息,就逐步降低MTU值,直到成功。

4.3 NAT穿透与防火墙配置

NAT(网络地址转换)是公网推流的最大障碍。RTSP的麻烦在于:控制信令和媒体流走不同端口,NAT设备经常只转发信令端口,把RTP/UDP端口堵死。

常见的穿透方案有三种:

  1. UDP打洞(Hole Punching):客户端先向服务器发一个UDP包,在NAT上开一个洞,服务器再用这个洞回推流。
  2. TCP隧道:所有RTP数据都通过RTSP的TCP连接传输(interleaved模式),彻底绕过UDP端口问题。
  3. STUN/TURN中继:通过公网服务器中转,适合对称NAT场景。

我个人最推荐的是TCP interleaved模式,因为它最简单、最稳定。配置方式就是在transport头里指定:

Transport: RTP/AVP/TCP;interleaved=0-1

这样RTP和RTCP数据都复用同一个TCP连接,NAT设备只需要维护一条会话。代价是延迟会高一些,但换来的是极高的穿透成功率。

防火墙配置方面,你需要开放的端口:

协议 端口 方向 说明
TCP 554 入站 RTSP控制信令
UDP 5000-5050 入站/出站 RTP/RTCP媒体流(UDP模式)
TCP 5000-5050 入站/出站 RTP/RTCP媒体流(TCP模式)

小技巧:如果客户网络策略严格,可以只开TCP 554端口,然后强制所有流量走interleaved模式。这样防火墙配置最简单,也最安全。

4.4 整体决策流程

说了这么多,到底怎么选?我画了一张流程图,帮你快速决策:

RTSP网络传输模式决策流程 开始评估网络环境 是否公网? 是 推荐TCP interleaved 否 局域网:UDP优先 丢包率<5%? 是 保持UDP模式 否 切换TCP模式 防火墙拦截UDP? 是 强制TCP interleaved 否 尝试UDP打洞 配置MTU分片策略(≤1400字节) 完成传输优化配置

这张图的核心逻辑很简单:先判断网络类型,再根据丢包和防火墙情况做调整,最后统一配置MTU。我每次做项目都按这个流程走,基本没出过问题。

最后提醒一句:别迷信UDP的低延迟。在公网环境下,TCP的稳定性和穿透能力远比那几十毫秒的延迟重要。除非你在纯局域网内做实时监控,否则我建议你默认走TCP interleaved模式。