11、RTP/RTCP协议栈:RTP包头解析、RTCP控制报文类型、SRTP安全传输
各位同学,今天我们来聊聊WebRTC中最核心的传输协议——RTP/RTCP。说实话,很多做WebRTC开发的朋友,一开始都被这堆协议搞晕过。我当年第一次看RFC 3550的时候,也是硬着头皮啃下来的。但等你真正理解了,就会发现这些设计其实非常巧妙。
RTP包头:12字节的玄机
RTP(Real-time Transport Protocol)是WebRTC传输音视频数据的"卡车"。它的包头只有12字节,但每个字段都有讲究。来,我们直接看结构:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
我来拆解一下这几个关键字段:
- V(Version):版本号,固定为2。目前主流就是RTPv2。
- P(Padding):填充位。有时候为了对齐,会在包尾加填充字节。我在做音频编解码对接时遇到过,某些硬件编码器会强制填充,这时候你得知道怎么处理。
- X(Extension):扩展位。WebRTC里经常用到,比如OneByte扩展头,用来传一些自定义信息。
- CC(CSRC Count):贡献源数量。混音场景下会用,比如多人会议。
- M(Marker):标记位。视频里通常表示一帧的结束,音频里表示会话的开始。
- PT(Payload Type):负载类型。告诉接收方这个包是H264、VP8还是Opus。嗯,这里要注意,WebRTC里PT值可以动态协商,不是固定的。
- Sequence Number:序列号。用来检测丢包和排序。我见过有人把这个和RTP时间戳搞混,其实序列号是递增的,时间戳是采样时钟。
- Timestamp:时间戳。音频用48kHz时钟,视频用90kHz时钟。为什么视频用90kHz?因为这是MPEG标准里定的,方便计算帧率。
- SSRC:同步源标识。每个RTP流有一个唯一的SSRC,用来区分不同的媒体流。
核心要点:RTP包头虽然只有12字节,但每个字段都承载着关键信息。序列号和时间戳是RTP的"双引擎",一个负责顺序,一个负责时序。
RTCP控制报文:不只是报告
RTCP(RTP Control Protocol)是RTP的"管家"。它不传媒体数据,只传控制信息。RTCP有五种基本报文类型,我按使用频率排个序:
| 类型 | 名称 | 作用 |
|---|---|---|
| 200 | SR(Sender Report) | 发送方报告,包含发送统计和NTP时间戳 |
| 201 | RR(Receiver Report) | 接收方报告,包含丢包率、抖动等 |
| 202 | SDES(Source Description) | 源描述,包含CNAME等信息 |
| 203 | BYE | 退出通知 |
| 204 | APP | 应用自定义 |
我个人觉得,SR和RR是最重要的。为什么?因为WebRTC的拥塞控制全靠它们。你看这个SR报文结构:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P| RC | PT=200 | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SSRC of sender |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NTP timestamp, most significant word |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NTP timestamp, least significant word |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTP timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sender's packet count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| sender's octet count |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| report block(s) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
这里有个细节:NTP时间戳和RTP时间戳同时存在。NTP是绝对时间,RTP是媒体时钟。通过这两个时间戳的映射,接收方可以计算出网络延迟。我曾经在调试音画同步时,就是靠这个映射关系定位到问题的。
避坑指南:RTCP的发送间隔有严格限制。RFC 3550规定,RTCP带宽不能超过会话总带宽的5%。如果你在项目中遇到RTCP报文过多导致网络拥塞,记得检查一下带宽分配。
SRTP:给RTP加把锁
RTP本身是明文传输的。你想想看,如果视频会议里被人抓包,那画面太美不敢看。所以WebRTC强制使用SRTP(Secure RTP)进行加密。
SRTP不是重新发明轮子,它是在RTP基础上加了加密和认证。核心机制就两个:
- 加密:使用AES算法加密RTP负载。默认是AES-128,密钥通过DTLS-SRTP协商。
- 认证:使用HMAC-SHA1对RTP包进行完整性校验。防止中间人篡改。
SRTP的包格式和RTP几乎一样,只是在尾部多了两个字段:
| RTP Header | RTP Payload (encrypted) | MKI (optional) | Authentication Tag |
MKI是Master Key Identifier,用来标识使用哪组密钥。Authentication Tag是认证标签,接收方用这个来验证包是否被篡改。
我记得有一次,客户反馈视频通话偶尔出现花屏。排查了半天,发现是SRTP认证失败导致丢包。原因是密钥协商时,DTLS握手超时了。后来我们调整了超时时间,问题就解决了。
注意事项:SRTP的认证标签长度可以配置。WebRTC默认是80位(10字节),但有些场景为了节省带宽,可以缩短到32位。不过我不建议这么做,安全性会打折扣。
协议栈全景图
说了这么多,我们来画一张图,把RTP/RTCP/SRTP的关系理清楚:
从这张图可以看得很清楚:应用层生成媒体数据,交给SRTP加密,然后封装成RTP包,最后通过UDP发送。RTCP是并行通道,负责反馈网络质量。
实际开发中,你不需要手动处理这些协议细节。WebRTC的Native API已经封装好了。但理解底层原理,能帮你更好地排查问题。比如:
- 如果视频卡顿,先看RTCP RR报文里的丢包率
- 如果音画不同步,检查RTP时间戳和NTP时间戳的映射
- 如果连接失败,确认DTLS-SRTP密钥协商是否完成
好了,这一章的内容就到这里。RTP/RTCP是WebRTC的"血管",搞懂了它们,你就掌握了WebRTC传输的核心。
一句话总结:RTP传数据,RTCP传控制,SRTP保安全。三者配合,构成了WebRTC的传输基石。