数据通道:RTCDataChannel 可靠与不可靠传输

发布时间:2026/7/8 1:56:19

数据通道:RTCDataChannel 可靠与不可靠传输 数据通道RTCDataChannel 可靠与不可靠传输WebRTC 不止能传音视频还能通过 DataChannel 传任意数据文字消息、文件、游戏数据、白板指令。这篇讲 RTCDataChannel 的用法、可靠与不可靠模式、消息顺序、流量控制以及实际应用场景。大家好我是黒漂技术佬。提到 WebRTC大家第一反应都是视频通话。但 WebRTC 还有一个很有用的东西——RTCDataChannel在点对点连接上传输任意数据和音视频走同一条通道。聊天消息、文件传输、白板协作、游戏同步、远程控制……都能用 DataChannel 做。低延迟、P2P、不经过服务器打洞成功的话。这篇讲 DataChannel 的用法、可靠/不可靠模式、顺序控制、常用场景。一、RTCDataChannel 是什么作用在 RTCPeerConnection 上建立数据通道点对点传输任意二进制或文本数据。特点低延迟P2P 直连延迟比 WebSocket 还低多种传输模式可靠有序 / 不可靠无序按需选择任意数据字符串、二进制、文件什么都能传加密DTLS 加密安全和音视频复用连接不用额外建连接和 WebSocket 比RTCDataChannelWebSocket架构P2P可能走TURN中继客户端-服务器延迟低直连较高经过服务器转发传输模式可靠/不可靠有序/无序可靠有序服务器成本低只有信令高所有数据过服务器穿透问题需要处理 NAT没有复杂度高低适合实时性要求高、数据量大、不想走服务器的场景。二、基本用法创建 DataChannel发起方创建constdataChannelpc.createDataChannel(my-channel,{ordered:true,// 保证顺序maxRetransmits:3// 最多重传3次});第一个参数是标签channel name第二个是配置。接收方监听pc.ondatachannel(event){constdataChannelevent.channel;dataChannel.onopen()console.log(数据通道打开了);dataChannel.onmessage(event){console.log(收到消息:,event.data);};};发起方 createDataChannel 后接收方会触发 ondatachannel 事件。发送数据// 发送字符串dataChannel.send(Hello WebRTC!);// 发送二进制constbuffernewArrayBuffer(100);dataChannel.send(buffer);// 发送 BlobdataChannel.send(newBlob([file data]));字符串、ArrayBuffer、Blob、TypedArray 都能发。接收数据dataChannel.onmessage(event){constdataevent.data;if(typeofdatastring){// 字符串console.log(文本消息:,data);}elseif(datainstanceofArrayBuffer){// 二进制console.log(二进制数据长度:,data.byteLength);}};通道状态dataChannel.readyState// connecting | open | closing | closeddataChannel.onopen(){};dataChannel.onclose(){};dataChannel.onerror(err){};关闭通道dataChannel.close();三、可靠 vs 不可靠有序 vs 无序DataChannel 有四个模式根据场景选两个关键参数orderedtrue消息按发送顺序到达有序false消息可能乱序到达无序maxRetransmits / maxPacketLifeTime设置了就是可靠模式丢了重传都不设null就是不可靠模式丢了就丢了四种组合1. 可靠有序默认{ordered:true}和 TCP 类似保证可靠、保证顺序丢包会重传队头阻塞适合聊天消息、文件传输、信令2. 可靠无序{ordered:false,maxRetransmits:3}保证送达但不保证顺序比有序快一点不会队头阻塞适合消息之间没有依赖关系的场景3. 不可靠有序很少用{ordered:true,maxRetransmits:0}保证顺序但丢了不重传用得少4. 不可靠无序类似 UDP{ordered:false,maxRetransmits:0}不保证送达不保证顺序延迟最低最快适合实时游戏状态、鼠标位置、传感器数据怎么选场景模式原因文字聊天可靠有序消息不能丢顺序不能乱文件传输可靠有序数据必须完整顺序不能错游戏同步不可靠无序实时最重要旧数据丢了没关系鼠标位置/白板笔画不可靠有序顺序重要丢几个点没事实时传感器数据不可靠无序最新的最重要旧的丢了无所谓四、常用配置参数完整配置constchannelpc.createDataChannel(channel-name,{ordered:true,// 是否有序maxPacketLifeTime:100,// 重传最长时间毫秒和maxRetransmits二选一maxRetransmits:3,// 最大重传次数protocol:,// 子协议自定义negotiated:false,// 是否预先协商好id:0// 通道IDnegotiated为true时指定});maxPacketLifeTime vs maxRetransmits两个都是控制可靠程度的二选一maxPacketLifeTime最多重传多久时间限制maxRetransmits最多重传几次次数限制都不设就是完全不可靠。negotiated 模式默认 false一方 create另一方 ondatachannel 接收。设为 true两边约定好 id各自 create不用等对方事件。适合提前知道通道数量的场景。五、流量控制与缓冲发送缓冲发送太快的话数据会存在缓冲区里。bufferedAmountconsole.log(缓冲区字节数:,dataChannel.bufferedAmount);bufferedAmountLowThreshold缓冲区低于这个值时触发 bufferedamountlow 事件dataChannel.bufferedAmountLowThreshold1024*1024;// 1MBdataChannel.onbufferedamountlow(){// 缓冲区低于阈值了可以继续发了sendMoreData();};发送大文件的做法不能一次性全发会撑爆缓冲区。分片发送控制速度constCHUNK_SIZE16*1024;// 每片16KBletoffset0;functionsendFile(file){functionsendNext(){while(offsetfile.sizedataChannel.bufferedAmount1024*1024){constchunkfile.slice(offset,offsetCHUNK_SIZE);dataChannel.send(chunk);offsetCHUNK_SIZE;}if(offsetfile.size){// 缓冲区满了等有空间了再发dataChannel.onbufferedamountlowsendNext;}else{console.log(文件发送完成);}}sendNext();}六、多通道一个 PeerConnection 可以建多个 DataChannel各干各的// 聊天通道可靠有序constchatChannelpc.createDataChannel(chat,{ordered:true});// 游戏数据通道不可靠无序constgameChannelpc.createDataChannel(game,{ordered:false,maxRetransmits:0});// 文件传输通道可靠有序单独一条不影响聊天constfileChannelpc.createDataChannel(file,{ordered:true});不同通道互不干扰。比如传大文件的时候聊天消息不会被卡住。七、实际应用场景场景 1文字聊天// 发送chatChannel.send(JSON.stringify({type:message,user:张三,text:你好,time:Date.now()}));// 接收chatChannel.onmessage(e){constmsgJSON.parse(e.data);displayMessage(msg);};P2P 聊天消息不经过服务器隐私好延迟低。场景 2文件传输分片发送带元信息// 发送方先发文件信息再发数据fileChannel.send(JSON.stringify({type:file-info,name:photo.jpg,size:file.size}));// 然后分片发文件内容...// 接收方收完信息收数据最后拼起来letfileData[];fileChannel.onmessage(e){if(typeofe.datastring){constinfoJSON.parse(e.data);// 记录文件信息}else{fileData.push(e.data);// 收完了拼起来下载}};P2P 传文件不占服务器带宽速度快直连的话。场景 3实时游戏同步// 发送玩家位置不可靠无序快就行functionsendPosition(x,y){constdatanewFloat32Array([x,y]);gameChannel.send(data);}// 接收更新位置gameChannel.onmessage(e){const[x,y]newFloat32Array(e.data);updatePlayerPosition(x,y);};低延迟适合快节奏游戏。场景 4白板协作// 发送画笔轨迹whiteboardChannel.send(JSON.stringify({type:draw,x:100,y:200,color:#ff0000}));配合视频通话远程教学、协作办公。场景 5远程控制发送鼠标键盘事件远程控制对方电脑。八、和音视频配合DataChannel 和音视频走同一个 PeerConnection不用额外建连constpcnewRTCPeerConnection(config);// 加音视频stream.getTracks().forEach(tpc.addTrack(t,stream));// 加数据通道constchatChannelpc.createDataChannel(chat);一个连接搞定所有视频、音频、聊天、文件。信令也可以走 DataChannel连接建立之后后续的控制消息比如静音、开关摄像头可以走 DataChannel不用走信令服务器了。九、常见坑坑 1数据太大发不出去单次 send 不能太大浏览器有限制一般 64KB 左右。大文件一定要分片。坑 2发太快缓冲区爆了不看 bufferedAmount 一股脑发会内存暴涨甚至丢数据。要做流量控制。坑 3通道没打开就发消息readyState 不是 open 的时候 send 会报错。要等 onopen 之后再发。坑 4不可靠模式真的会丢别在不可靠通道传重要数据丢了就是丢了不会重传。坑 5不同浏览器支持差异老浏览器可能不支持某些参数比如 maxPacketLifeTime。用 adapter.js 特性检测。坑 6二进制和字符串混着发接收方要判断 data 类型字符串和二进制处理方式不一样。十、性能考量延迟P2P 直连延迟很低同城几十毫秒走 TURN 中继延迟高一些看 TURN 服务器位置吞吐量直连的话带宽取决于两端的上行/下行速度能跑满带宽。走 TURN 的话受限于 TURN 服务器的带宽。多少条通道合适不同用途分开建通道互不影响但也别建太多有开销一般 2-5 条足够聊天、文件、游戏数据……十一、本篇小结RTCDataChannel 在 PeerConnection 上传输任意数据P2P、低延迟四种模式可靠有序默认、可靠无序、不可靠有序、不可靠无序可靠有序适合聊天、文件传输不可靠无序适合游戏、实时数据大文件要分片发送注意流量控制bufferedAmount一个连接可以建多个 DataChannel不同用途分开常见场景文字聊天、文件传输、游戏同步、白板协作、远程控制和音视频复用同一个连接不用额外建连下一篇讲信令服务器设计与实现怎么搭一个 WebRTC 的信令服务。我是黒漂技术佬。

相关新闻