RTCDataChannel必须依附RTCPeerConnection且待其connectionState为"connected"后方可安全发送数据;默认ordered:true与maxRetransmits:0组合会导致丢包时后续消息全阻塞,应按场景选配ordered:false或maxPacketLifeTime等参数。

RTCDataChannel 不能脱离 RTCPeerConnection 单独使用,必须等连接真正建立(connectionState === "connected")后才能安全发数据;直接 createDataChannel() 后立刻 send(),90% 的情况会静默失败。
dataChannel.send() 不报错但对方收不到?检查 ordered 和 maxRetransmits 配置
默认 { ordered: true, maxRetransmits: 0 } 实际是“有序 + 无限重传”,不是“可靠”而是“卡死式可靠”。弱网丢一个包,后续所有消息全堵在 SCTP 缓冲区,bufferedAmount 持续上涨,最终触发断连。
- 实时日志、游戏帧、协作光标:用
{ ordered: false, maxRetransmits: 0 }(不可靠、无序) - 需顺序但可容忍延迟的指令:用
{ ordered: true, maxPacketLifeTime: 2000 }(限制重传窗口为 2 秒) -
maxRetransmits和maxPacketLifeTime互斥,只设一个 - Safari ≤16.4 不支持
maxPacketLifeTime,要用就降级为maxRetransmits: 0+ 应用层重传
发送 HTML 字符串时,e.data 类型不固定,接收端必须判断
send() 传字符串,接收端 e.data 可能是 string 或 Blob,取决于浏览器实现和传输大小。不加判断直接 .innerHTML = e.data 会出错。
- 统一转成字符串:
const html = typeof e.data === "string" ? e.data : await e.data.text(); - 渲染前建议用
DOMParser校验结构:new DOMParser().parseFromString(html, "text/html") - 含相对路径的资源(如
<img src="logo.png">)需提前转data:URL 或约定 CDN 域名 - 超 64KB 的 HTML 必须走
ordered: false,否则大概率卡住
大文件分片传输,单次 send() 别超 64KB
不是理论上限,而是 SCTP + TLS 加密 + 浏览器实现共同导致的实际瓶颈。超过后常见报错:Failed to execute 'send' on 'RTCDataChannel': Data cannot be sent because the underlying data transport is not ready,尤其在 iOS Safari 和低端 Android 上更敏感。
立即学习“前端免费学习笔记(深入)”;
- 推荐分片大小:32–48KB(留出协议头和加密开销余量)
- 每片加唯一
id和total字段,接收端按序拼接,避免依赖ordered: true - 关键分片发送后,监听
dataChannel.bufferedAmount === 0再发下一片,比轮询更稳 - 不要信任
onbufferedamountlow——它在 Chrome 中经常不触发,Firefox 表现略好
最易被忽略的是:即使 dataChannel.readyState === "open",网络也可能已中断 1–2 秒,此时 send() 仍成功返回,但数据永远到不了对端。真要保交付,得自己加消息 ID + ACK 回执,WebRTC 不提供这个能力。



















