一、数据通道是什么?先别急着写代码

WebRTC 数据通道,说白了就是浏览器之间的一条「隐形网线」。

它不经过服务器中转,直接在两个浏览器之间传数据。我刚开始接触时也觉得神奇——两个网页居然能直接对话?

嗯,确实可以。而且它用的是 SCTP 协议,不是传统的 TCP 或 UDP。你想想看,这意味着什么?

  • 可靠传输:默认情况下,数据不会丢,顺序也不会乱
  • 低延迟:没有服务器中转,数据直达
  • 安全加密:DTLS 加密,跟 HTTPS 一个级别

我个人习惯把数据通道比作「WebSocket 的升级版」。WebSocket 还要连服务器,数据通道直接点对点。

核心要点:数据通道建立在 PeerConnection 之上。没有连接,就没有通道。

二、创建数据通道:就这么简单

创建数据通道,只需要一行代码。真的,就一行。

const dataChannel = peerConnection.createDataChannel('myLabel');

这里的 'myLabel' 是通道名称。你可以随便起名,但两端要约定好。

我记得第一次写的时候,以为还要配置什么参数。其实默认就够用了。当然,你也可以传第二个参数:

const dc = pc.createDataChannel('chat', {
  ordered: true,        // 保证顺序
  maxRetransmits: 3     // 最多重传3次
});

这里有个小坑:maxRetransmitsmaxPacketLifeTime 不能同时设置。我当初踩过这个坑,两个都设了,结果浏览器直接报错。

我的建议:文本聊天用 maxRetransmits,实时游戏用 maxPacketLifeTime。前者保证送达,后者保证时效。

三、监听事件:通道的「心跳」

数据通道有四个核心事件。我按使用频率排个序:

事件 触发时机 我常用的场景
open 通道建立成功 显示「连接成功」提示
message 收到对方数据 处理聊天消息或文件
close 通道关闭 清理资源、显示断开提示
error 发生错误 日志记录、重连逻辑

代码怎么写?看这里:

dataChannel.onopen = () => {
  console.log('通道已打开');
  // 可以开始发消息了
};

dataChannel.onclose = () => {
  console.log('通道已关闭');
  // 清理工作
};

dataChannel.onerror = (err) => {
  console.error('通道错误:', err);
};

dataChannel.onmessage = (event) => {
  console.log('收到消息:', event.data);
};

为什么 open 事件这么重要?因为通道没打开之前,你发消息是发不出去的。我曾经在项目里犯过这个错——通道还没 ready 就发数据,结果消息全丢了。

避坑指南:一定要等 open 事件触发后再发消息。可以用一个标志位控制:let isOpen = false;,在 onopen 里设为 true。

四、发送文本消息:实战演练

发送消息用 send() 方法。就这么简单:

dataChannel.send('你好,世界!');

但要注意,send() 只能传字符串、Blob、ArrayBuffer 或 ArrayBufferView。传对象?不行,得先 JSON 序列化:

const msg = {
  type: 'chat',
  content: '你好',
  timestamp: Date.now()
};

dataChannel.send(JSON.stringify(msg));

接收端再解析回来:

dataChannel.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log(data.type, data.content);
};

我习惯在消息里加一个 type 字段。这样后期扩展功能(比如文件传输、信令交互)就方便多了。

五、完整示例:一个迷你聊天室

把上面所有知识点串起来,就是一个最简单的聊天功能:

// 创建连接
const pc = new RTCPeerConnection();
const dc = pc.createDataChannel('chat');

let isChannelReady = false;

dc.onopen = () => {
  isChannelReady = true;
  console.log('✅ 通道已就绪');
};

dc.onmessage = (event) => {
  console.log('💬 收到:', event.data);
};

// 发送消息
function sendMessage(text) {
  if (!isChannelReady) {
    console.warn('⚠️ 通道还没准备好');
    return;
  }
  dc.send(text);
}

// 使用
sendMessage('Hello WebRTC!');

这段代码虽然简单,但已经覆盖了数据通道的核心流程:创建 → 监听 → 发送。

记住:数据通道是双向的。一端发送,另一端就能收到。不需要区分「客户端」和「服务器」。

六、知识体系总览

下面这张图总结了本章的核心逻辑。我画的时候特意把「连接建立」放在最前面——这是所有操作的前提。

数据通道核心流程 1. 创建 PeerConnection 2. createDataChannel() 3. 监听 open / message / close / error 4. send() / onmessage 双向通信 注意:所有操作都建立在连接建立成功的基础上

七、常见问题与避坑

最后分享几个我实际项目中遇到的坑:

  • 通道未打开就 send:消息会静默丢失。解决方案:用 readyState 检查状态。
  • 两端同时 createDataChannel:会导致通道重复。建议一端创建,另一端在 ondatachannel 里接收。
  • 消息太大:SCTP 有消息大小限制(通常 16KB-64KB)。大文件要分片发送。
小技巧:调试时可以用 dataChannel.readyState 查看当前状态。它有三个值:connectingopenclosingclosed

好了,数据通道入门就到这里。代码不多,但每个细节都值得你亲手敲一遍。下次我们聊聊如何传输二进制数据——文件、图片、视频片段,都能走数据通道。


公众号:蓝海资料掘金营,微信deep3321