DataChannelController 与数据通道 · 传任意数据

WebRTC 不止传音视频,还能传任意数据——文件、游戏状态、聊天消息。这一章读 pc/data_channel_controller.cc:数据通道的控制面,SctpDataChannel 如何架在 SCTP-over-DTLS 之上,以及可靠性/有序性怎么配置。SCTP 协议本身留到第 8 部分深挖。

作者 David更新于 第 14 篇(共 112 篇)

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」。

本页目录