4. 网络传输优化:TCP vs UDP模式选择、MTU与MSS调优、NAT穿透与防火墙策略
网络传输这块,说白了就是RTSP推流的"血管"。血管堵了,再好的编码器、再强的服务器都白搭。我在项目中见过太多案例——推流端配置拉满,结果画面卡成PPT,最后查下来全是网络层的问题。
这一章我们聚焦三个核心问题:选TCP还是UDP?怎么让数据包不碎不丢?怎么穿透内网和防火墙?嗯,一个一个来。
4.1 TCP vs UDP:RTSP推流的传输层抉择
RTSP本身是控制协议,但媒体数据的传输方式可以灵活选择。我个人的习惯是:先看场景,再定协议。
| 对比维度 | TCP | UDP |
|---|---|---|
| 可靠性 | 有重传、有序到达 | 无重传、可能丢包乱序 |
| 延迟 | 较高(重传+拥塞控制) | 较低(无确认机制) |
| 防火墙友好度 | 高(HTTP/HTTPS端口常见) | 低(容易被拦截) |
| 适用场景 | 公网、弱网、要求稳定 | 局域网、低延迟直播 |
核心结论:公网推流优先选TCP,局域网低延迟场景选UDP。但要注意——RTSP over UDP的端口范围通常需要协商,很多防火墙默认会拦截高位UDP端口。
我记得有一次帮客户排查推流卡顿,他们坚持用UDP,说延迟低。结果发现运营商对UDP流量做了限速,丢包率高达15%。换成TCP后,虽然延迟多了几十毫秒,但画面流畅了。你想想看,丢包15%的情况下,UDP的画面基本没法看。
4.1.1 RTP over RTSP(TCP模式)
TCP模式下,RTP数据包被封装在RTSP的TCP连接中传输。具体做法是使用Transport: RTP/AVP/TCP;unicast;interleaved=0-1这样的头字段。
// 客户端请求
SETUP rtsp://example.com/stream RTSP/1.0
CSeq: 3
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
// 服务器响应
RTSP/1.0 200 OK
CSeq: 3
Transport: RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=12345678
Session: 987654321
这里interleaved=0-1表示RTP数据使用通道0,RTCP数据使用通道1。数据直接在同一个TCP连接里交错发送。好处很明显——只需要一个端口,防火墙配置简单。
实战技巧:TCP模式下的RTP数据包前面会加4字节的帧头($ + 通道号 + 2字节长度)。解析时一定要按这个格式拆包,我见过有人直接当裸RTP解析,结果全乱套了。
4.1.2 RTP over UDP(UDP模式)
UDP模式使用独立的端口传输RTP和RTCP。典型的Transport头是这样的:
Transport: RTP/AVP;unicast;client_port=5000-5001
客户端端口5000收RTP,5001收RTCP。服务器会从自己的端口向这两个端口发数据。
为什么会有人坚持用UDP?因为延迟确实低。没有TCP的慢启动、拥塞控制、重传机制,数据包发出去就不管了。在局域网内,UDP的端到端延迟可以控制在10ms以内。
注意:UDP模式需要额外的NAT穿透处理。如果推流端和服务器之间有NAT设备,必须确保RTP和RTCP的端口映射都正确。我曾经遇到一个案例,RTP端口映射了但RTCP没映射,结果服务器收不到接收报告,一直以最低码率推流。
4.2 MTU与MSS调优:让数据包不碎不丢
MTU(最大传输单元)和MSS(最大分段大小)是网络传输中容易被忽视的参数。说白了,MTU是网络链路层能承载的最大数据包大小,MSS是TCP层能发送的最大数据段大小。
以太网的默认MTU是1500字节。减去IP头(20字节)和TCP头(20字节),MSS就是1460字节。但问题来了——RTP包的大小可能超过这个值。
4.2.1 为什么MTU调优很重要
当IP包大小超过MTU时,路由器会进行分片。分片带来的问题:
- 性能下降:分片和重组消耗CPU资源
- 丢包放大:一个分片丢了,整个包都得重传
- 延迟增加:重组需要等待所有分片到达
我建议在推流前先做MTU探测。用ping -M do -s 1472 target_ip(Linux)或ping -f -l 1472 target_ip(Windows)测试路径MTU。
# Linux下探测路径MTU
ping -M do -s 1472 192.168.1.100
# 如果返回"Message too long",减小size重试
ping -M do -s 1400 192.168.1.100
# 直到成功,得到路径MTU = size + 28
关键参数:RTP包大小建议控制在路径MTU的90%以内。比如路径MTU是1500,RTP包不要超过1350字节。留出余量给IP选项和隧道开销。
4.2.2 MSS调优实战
对于TCP模式,MSS调优直接影响传输效率。MSS太大,容易触发IP分片;MSS太小,传输效率低。
| 场景 | 推荐MSS | 说明 |
|---|---|---|
| 标准以太网 | 1460 | MTU 1500 - IP头20 - TCP头20 |
| PPPoE拨号 | 1452 | 额外8字节PPPoE头 |
| VPN隧道 | 1400-1440 | 取决于隧道封装开销 |
| 无线网络 | 1300-1400 | 无线链路不稳定,建议偏小 |
我个人习惯在推流服务器上设置ip tcp mss来全局调整:
# Linux下设置TCP MSS为1400
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --set-mss 1400
避坑指南:我曾经在云服务器上部署推流服务,发现公网推流总是间歇性卡顿。排查了三天,最后发现是云平台的虚拟化网络MTU只有1400,而我的MSS设成了1460。每次超过1400的包都被分片,分片丢失导致TCP重传,重传又加剧拥塞。把MSS降到1360后,问题彻底解决。
4.3 NAT穿透与防火墙策略
NAT穿透是公网推流绕不开的坎。RTSP的控制信令和媒体流走不同的端口,NAT设备需要正确处理这些映射关系。
4.3.1 NAT类型与穿透方案
NAT分为四种类型,穿透难度依次递增:
| NAT类型 | 特点 | 穿透难度 |
|---|---|---|
| 全锥形 | 任何外部主机都能通过映射地址访问 | 低 |
| 受限锥形 | 只允许内部主机曾访问过的外部IP访问 | 中 |
| 端口受限锥形 | 限制外部IP和端口 | 中高 |
| 对称NAT | 每个外部目标使用不同的映射 | 高 |
对于RTSP推流,我推荐以下穿透策略:
- TCP模式:使用单一端口,NAT映射简单,推荐首选
- UDP模式:使用STUN/TURN服务器辅助穿透
- 对称NAT:必须使用TURN中继,否则无法穿透
4.3.2 防火墙策略配置
防火墙配置的核心原则是:最小权限,按需开放。
# 推流服务器防火墙规则示例(iptables)
# 允许RTSP控制端口(默认554)
iptables -A INPUT -p tcp --dport 554 -j ACCEPT
# 允许RTP/RTCP UDP端口范围(假设使用50000-51000)
iptables -A INPUT -p udp --dport 50000:51000 -j ACCEPT
# 允许已建立的连接回包
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 默认拒绝其他入站
iptables -P INPUT DROP
注意:UDP端口范围不要开太大。我见过有人直接开了1024-65535,这等于把防火墙关了。合理的做法是根据并发推流数计算端口需求,每个流需要2个端口(RTP+RTCP),再留20%余量。
4.3.3 实战中的NAT穿透方案
根据我的经验,不同场景的推荐方案:
- 局域网内推流:直接使用UDP,无需NAT处理
- 公网推流(推流端在NAT后):TCP模式 + 端口映射
- 公网推流(两端都在NAT后):TCP模式 + TURN中继
- 移动网络推流:TCP模式 + 自适应码率
我记得有一次给一个安防项目做方案,摄像头在多个不同运营商的NAT后面,推流到中心服务器。一开始用UDP模式,各种穿透失败。后来全部改成TCP模式,配合服务器端的端口复用,稳定运行了两年没出过问题。
核心建议:除非你对网络环境有绝对控制权(比如纯局域网),否则默认使用TCP模式。TCP的可靠性、防火墙友好度和NAT穿透便利性,远超过那点延迟优势。延迟问题可以通过调整TCP参数(如Nagle算法、窗口大小)来优化。
网络传输优化没有银弹。我的建议是:先跑通,再优化。先用TCP模式把推流跑起来,然后根据实际网络状况逐步调整MTU、MSS和防火墙策略。等系统稳定了,再考虑是否切换到UDP模式来降低延迟。