DataChannelController 与数据通道 · 传任意数据
WebRTC 不止传音视频,还能传任意数据——文件、游戏状态、聊天消息。这一章读 pc/data_channel_controller.cc:数据通道的控制面,SctpDataChannel 如何架在 SCTP-over-DTLS 之上,以及可靠性/有序性怎么配置。SCTP 协议本身留到第 8 部分深挖。
DataChannelController 与数据通道 · 传任意数据
WebRTC 的名气在音视频,但它还有一条常被低估的能力:数据通道(DataChannel)——在两个端点间传任意数据,文件、游戏同步、聊天、信令二次通道,都行。管理它的,是 PeerConnection 的 data_channel_controller_ 成员。这一章读它的控制面;SCTP 协议本身的硬核细节,留给第 8 部分。
数据通道站在哪一层
先定位。数据通道不走 RTP(RTP 是给实时音视频的),而是走 SCTP,再套在 DTLS 上:
DataChannel(应用 API)
└── SCTP(可靠/有序可调,第 8 部分)
└── DTLS(加密,第 3 部分)
└── ICE 选定的通路(第 2 部分)和音视频一样,它也复用同一条底层传输(BUNDLE 时),只是上层协议从 RTP 换成了 SCTP。SDP 里,它对应一条应用类型的 m-line(m=application ... webrtc-datachannel)。
DataChannelController:控制面
pc/data_channel_controller.cc 里的 DataChannelController,管理这一切。它的声明就点明了身份(pc/data_channel_controller.h):
// pc/data_channel_controller.h(节选)
class DataChannelController : public SctpDataChannelControllerInterface, ... {
// 创建一个数据通道(带 proxy,保证线程安全)
... InternalCreateDataChannelWithProxy(absl::string_view label, ...);
void OnChannelStateChanged(SctpDataChannel* channel, ...);
// 持有到 SCTP 传输的连接:DataChannelTransportInterface*
};- 它实现
SctpDataChannelControllerInterface——是各个SctpDataChannel的大管家。 CreateDataChannel(API 层)最终走到InternalCreateDataChannelWithProxy,造出一个SctpDataChannel并包上代理。- 它持有一个
DataChannelTransportInterface*——通往底层 SCTP 传输的出口。 - 通道状态变化(打开、关闭)通过
OnChannelStateChanged回上来,再通知应用。
SctpDataChannel:一条通道
每条数据通道是一个 SctpDataChannel(pc/sctp_data_channel.cc)。它是应用直接打交道的对象:send() 发数据、onmessage 收数据、onopen/onclose 感知状态。多条数据通道复用同一个 SCTP association(第 8 部分),靠 SCTP 的流(stream)id 区分——就像 BUNDLE 靠 SSRC 区分媒体,SCTP 靠 stream id 区分通道。
可靠性与有序性:可调
数据通道最迷人的地方,是它的传输语义可配——这也是它比「裸 UDP」或「裸 TCP」都灵活的原因:
数据通道的可靠性和有序性,创建时可调——这继承自底层 SCTP 的能力。 两个旋钮:
- 有序 vs 无序(
ordered):要不要保证「先发的先到」。聊天消息要有序;而实时游戏状态可能宁可乱序也要低延迟。 - 可靠性(
maxRetransmits/maxPacketLifeTime):丢了要不要重传、重传几次 / 多久内有效。设成「完全可靠」就像 TCP(必达);设成「最多重传 0 次」就像 UDP(尽力而为);还能取中间态——「最多重传 3 次」或「50ms 内才重传」。
这种「部分可靠(partial reliability)」正是 SCTP 相对 TCP 的杀手锏(RFC 3758,第 8 部分细讲):你按数据的性质,精确选择「多可靠」。一条通道可以完全可靠有序(传文件),另一条可以不可靠无序(传实时位置),它们复用同一个 association。DataChannelController 把应用设的这些参数,翻译成对 SCTP 传输的配置。
小结与下一章
数据通道让 WebRTC 传任意数据,走 SCTP-over-DTLS(不走 RTP),对应 SDP 一条 application m-line,BUNDLE 时复用同一条底层传输。data_channel_controller_ 即 DataChannelController 是控制面大管家:InternalCreateDataChannelWithProxy 造出 SctpDataChannel(多条通道靠 SCTP stream id 区分),并把应用设的有序性 / 可靠性(有序?重传几次?)翻译成 SCTP 配置——部分可靠是它相对 TCP/UDP 的独特优势。SCTP 协议本身见第 8 部分。
会话建立的最后一块拼图,是统计——getStats() 怎么从散落在各个线程各个对象里的数据,汇总成一份报告。下一章读 RtcStatsCollector,收尾第 1 部分。👉 RtcStatsCollector:统计怎么汇总。
参考资料
- [1] libwebrtc 源码.
pc/data_channel_controller.h/.cc(DataChannelController、InternalCreateDataChannelWithProxy)。 - [2] libwebrtc 源码.
pc/sctp_data_channel.h/.cc(SctpDataChannel)。 - [3] IETF RFC 8831「WebRTC Data Channels」、RFC 8832「Data Channel Establishment Protocol」。