跳到主要内容

本篇是 WebRTC 101 系列 第 5 篇,讲 RTCDataChannel:不靠音视频、纯跑任意数据的点对点通道,以及它和 WebSocket 到底怎么选。

RTCDataChannel:SCTP over DTLS,什么时候该用它

前面的篇章都在讲音视频;但 WebRTC 里还有一条"不搞媒体也能用"的通道——数据通道。它是做游戏状态同步、文件传输、白板协作、以及先用文本协议握手再升级音视频这类场景的关键。

1. 它底层是什么

一句话:DataChannel = 跑在 WebRTC 加密传输之上的 SCTP 流

  • **SCTP(流控制传输协议)**是它真正的载体(RFC 8831/8832),而 SCTP 本身又是 over DTLS(RFC 8261)——和第 4 篇媒体共用同一条 DTLS 隧道。
  • 因为搭在 WebRTC 已经打通的通道上,它天然继承了:P2P 路径、端到端加密、ICE 打洞后的可达性。
  • 对应用而言,它暴露成像 WebSocket 一样的 API(onopen/onmessage/send()/close()),但能力比 WebSocket 强的地方在于——你可以选择可靠性策略

2. 关键选项:不只是"可靠或不可靠"

创建通道时(createDataChannel(label, options))可定以下参数,创建后不可改

选项含义默认
ordered是否保证按序到达true
maxRetransmits最多重传次数(丢了就放弃)无限制
maxPacketLifeTime数据最多存活毫秒(超时就丢)无限制
protocol应用自定义子协议名""
negotiated / id预协商通道:两端各自用同一个 id 创建自动协商

可靠性谱系(记住这个就够用):

完全可靠 + 有序 ← 默认,类似可靠流(传文件、同步状态)
部分可靠 + 有序 ← maxRetransmits / maxPacketLifeTime(限重传/限时,控制实时性)
乱序 + 部分可靠 ← ordered:false(游戏快照、实时位置,最新优先、旧了直接丢)

注意语义坑:maxRetransmitsmaxPacketLifeTime 二选一,不能同时设。做"丢包不补、过期作废"的实时消息(比如打字光标、游戏移动),选乱序 + 短 TTL,延迟最可控。

3. 最简可用片段(连接建立后)

// 发起方(offerer 通常负责建通道)
const dc = pc.createDataChannel("chat", { ordered: true });

// 对端在连接建立后收到
pc.ondatachannel = (event) => {
const dc = event.channel;
dc.onopen = () => dc.send("hi");
dc.onmessage = (e) => console.log("got:", e.data);
};

两个容易犯的错:

  • 通道要在连接建立前创建createDataChannel 应在 offer/answer 之前调用,这样它的协商才会出现在 SDP 里(你会在 SDP 看到一个 m=application … SCTP 段——这就是数据通道);
  • 对端不是"主动创建":对端通过 ondatachannel 拿到通道,而不是再调一次 createDataChannel(除非用了 negotiated: true + 相同 id)。

4. 背压:别把内存写爆

send() 是异步排队的,如果一直发而对方消化慢,bufferedAmount 会涨,最终爆内存。处理方式与 WebSocket 一致:

if (dc.bufferedAmount > 阈值) { 稍等; } // 简单节流
dc.onbufferedamountlow = () => 继续发; // 或监听 low 水位再继续

传大文件尤其要分块 + 看 bufferedAmount:每块设成可管理大小(几 KB~几百 KB),发完等 bufferedamountlow 再发下一块,才能跑满又不炸。

5. DataChannel vs WebSocket(选型表)

两者 API 几乎一样,但底层哲学不同:

维度WebSocketRTCDataChannel
拓扑客户端 ⇄ 服务器(长连接)端到端 P2P(可直连,必要时 TURN)
承载TCPSCTP over DTLS(基于已建好的 WebRTC 通道)
是否过你的服务器是(瓶颈/成本在服务器)直连时不过;走 TURN 时才过中继
可靠性选项只有可靠 + 有序可选乱序 / 限重传 / 限时
延迟更好(少一跳,且可放弃旧数据)
前置条件只要连服务器要先信令 + ICE 打通(复杂些)
加密TLS(客户端-服务器)DTLS(端到端)
穿越代理/NAT友好(TCP 80/443)依赖 STUN/TURN(UDP 常被墙)

怎么选的一句话

对方必然是你的服务器、或想要 HTTP 友好好穿透 → 用 WebSocket; 目标是两台对等端直接说话、或需要"最新优先可丢旧"的实时语义、或不想让数据都过你的服务器 → 用 DataChannel(先接受它的信令+ICE 复杂度)。

常见 combo:WebSocket 只做信令/房间,建好 PeerConnection 后,真正的业务数据(位置、白板、控制消息)走 DataChannel——许多实时应用就是这样分工的。

6. 使用场景速查

  • 文本/二进制消息:聊天、协作光标、游戏指令(延迟敏感用乱序+TTL);
  • 文件/流:P2P 传文件(无需服务器中转,第 0 篇提过 WebTorrent 即此类);
  • 与音视频并存:先 DataChannel 协商房间参数,再打开媒体;
  • 私有信令的备选:两个已建立会话的端再聊,不需要再经服务器。

参考与来源