数据通道与 SCTP 总览 · 传任意数据的那条路
数据通道传任意数据,底层走 SCTP over DTLS。这一章读 g3doc/sctp_transport.md:SctpTransport 如何封装一个 SCTP association、它和 DTLS 传输的关系、以及为什么 WebRTC 选 SCTP 而非直接用 TCP 或 UDP。为深入 dcSCTP 铺垫。
数据通道与 SCTP 总览 · 传任意数据的那条路
音视频讲完,进入 WebRTC 的第三种媒体——数据通道:传任意数据(文件、游戏状态、聊天)。第 1 部分的 DataChannelController 讲了它的控制面,第 8 部分深入它的底层协议 SCTP(net/dcsctp/,242 个文件)。先总览。
为什么是 SCTP
数据通道那章说过,数据通道走 SCTP over DTLS。为什么不直接用 TCP 或 UDP?
SCTP(Stream Control Transmission Protocol)提供了 TCP 和 UDP 都给不了的东西:可调的可靠性和多流**。**
- TCP 太死板 —— TCP 强制完全可靠 + 完全有序。但数据通道有时不想要这个(实时游戏状态宁可丢旧的、也不要等重传)。而且 TCP 的队头阻塞:一个包丢了,后面的全卡住等它——多路数据挤一条 TCP 时,一路的丢包拖累所有路。
- UDP 太原始 —— UDP 什么保证都没有,要可靠 / 有序得自己造轮子。
- SCTP 恰到好处 —— 它像“可配置的 TCP”:每条流的可靠性 / 有序性可独立设(完全可靠、部分可靠、完全不可靠都行),且多流——一个 association 里多条独立的流,一路丢包不阻塞其他路。这正好匹配数据通道“可靠性可调 + 多通道复用”的需求。
所以 WebRTC 选 SCTP——但不直接把 SCTP 跑在 IP 上(那要操作系统支持、还过不了 NAT),而是把它跑在 DTLS 之上(SCTP over DTLS over ICE),既借了 DTLS 的加密、又借了 ICE 的 NAT 穿越。一举多得。
SctpTransport:封装 association
WebRTC 里代表这条 SCTP 连接的,是 SctpTransport(pc/sctp_transport.h)。g3doc/sctp_transport.md 说明:
The
webrtc::SctpTransportclass encapsulates an SCTP association.
一个 SCTP association(关联)= 两端之间的一条 SCTP 连接(类似 TCP 的一个 connection)。所有数据通道复用这一个 association(靠 stream id 区分)。层次(g3doc):
SctpTransport(pc/)—— 面向用户的封装,引用计数、归 PeerConnection 拥有,暴露状态观察(状态变化回调在 network 线程)。SctpTransportInternal(media/sctp/)—— 内部实现,拥有两个对象:SCTP association + DTLS 传输。DTLS 传输是它收发字节的通道——SCTP 的包,经 DTLS 加密后发出。
dcSCTP:从零重写的 SCTP
这里有个重要的工程决定:WebRTC 的 SCTP 实现,是 Google 从零写的——dcSCTP(net/dcsctp/),而非沿用老的第三方库(usrsctp)。为什么大费周章重写一个协议栈?下一章细说,先剧透原因:老库难维护、难测试、有安全隐患,而 dcSCTP 用现代 C++、sans-IO 设计(不碰网络、纯逻辑、易测试)重写,更安全、更可控。这是 WebRTC “密码学 / 协议宁可自己写一个高质量的”哲学的又一次体现(呼应 AEC3 自带回声消除)。
小结与下一章
数据通道传任意数据,走 SCTP over DTLS over ICE。选 SCTP 因为它兼具 TCP 没有的**可调可靠性和多流(无队头阻塞),恰配数据通道需求。SctpTransport**(pc/,封装 association)/ SctpTransportInternal(拥有 association + DTLS 传输)是 WebRTC 侧的代表。SCTP 实现是 Google 从零重写的 dcSCTP(net/dcsctp/)。
下一章看 dcSCTP 本身——为什么重写、以及它精妙的 sans-IO 设计。👉 dcSCTP 从零实现。
参考资料
- [1] libwebrtc 源码.
g3doc/sctp_transport.md、pc/sctp_transport.h、media/sctp/sctp_transport_internal.h。 - [2] libwebrtc 源码.
net/dcsctp/(dcSCTP 实现)。 - [3] IETF RFC 9260「SCTP」、RFC 8831「WebRTC Data Channels」。