webrtc数据通道怎样使用

联启 网络工具 13

本文目录导读:

webrtc数据通道怎样使用-第1张图片-电脑手机工具软件下载 - 免费实用工具合集 | 联启科技

  1. 核心概念
  2. 步骤 1:建立信令连接
  3. 步骤 2:发送和接收数据
  4. 完整示例(同一页面测试)
  5. 常见问题 & 注意事项

WebRTC 的数据通道(Data Channel)允许你在两个浏览器(或端)之间直接传输任意数据,比如文本、文件、二进制数据等,而不需要经过服务器中转(但信令服务器是必需的)。

下面是使用 WebRTC 数据通道的完整步骤和核心代码示例。

核心概念

  • 信令:通过服务器交换会话描述(SDP)和 ICE 候选(candidate),建立连接,这不是数据通道独有的,是所有 WebRTC 建立连接的前提。
  • RTCPeerConnection:核心对象,管理整个连接。
  • createDataChannel:在发起方调用,创建数据通道。
  • ondatachannel:在接收方监听,当收到数据通道时触发。

步骤 1:建立信令连接

你需要一个服务器(WebSocket 或简单的 HTTP 转发)来交换 SDP 和 ICE 候选,这里假设你已经有一个信令服务器,可以发送和接收消息。

发送方(发起方)代码:

// 1. 创建 RTCPeerConnection 对象(可以配置 STUN/TURN 服务器)
const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] // 免费谷歌 STUN
});
// 2. 创建数据通道(必须在建立连接前创建)
const dataChannel = pc.createDataChannel('myChannel', {
  ordered: true,        // 是否保证顺序(默认 true)
  // maxRetransmits: 0, // 最大重传次数(最多选一个设置)
  // maxPacketLifeTime: 3000 // 或设置最大生存时间(毫秒)
});
// 3. 监听数据通道事件
dataChannel.onopen = () => {
  console.log('数据通道已打开');
  dataChannel.send('Hello from sender!');
};
dataChannel.onclose = () => console.log('通道关闭');
dataChannel.onerror = (err) => console.error('通道错误', err);
// 4. 创建并发送 Offer(发起连接)
pc.createOffer().then(offer => {
  return pc.setLocalDescription(offer);
}).then(() => {
  // 将本地 SDP(offer)发送给接收方(通过信令服务器)
  signalingServer.send({ type: 'offer', sdp: pc.localDescription });
});
// 5. 监听 ICE 候选并发送给对方
pc.onicecandidate = (event) => {
  if (event.candidate) {
    signalingServer.send({ type: 'candidate', candidate: event.candidate });
  }
};

接收方(响应方)代码:

// 1. 创建 RTCPeerConnection
const pc = new RTCPeerConnection({
  iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
});
// 2. 监听数据通道(接收方通过此事件获取)
pc.ondatachannel = (event) => {
  const dataChannel = event.channel;
  console.log('收到数据通道:', dataChannel.label);
  dataChannel.onopen = () => {
    console.log('接收方通道已打开');
  };
  dataChannel.onmessage = (event) => {
    console.log('收到消息:', event.data);
    // 可以回复消息
    dataChannel.send('Hello from receiver!');
  };
};
// 3. 接收 Offer,设置远程描述,创建 Answer(响应)
signalingServer.onmessage = async (msg) => {
  if (msg.type === 'offer') {
    await pc.setRemoteDescription(new RTCSessionDescription(msg.sdp));
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    // 将 Answer 发给发起方
    signalingServer.send({ type: 'answer', sdp: pc.localDescription });
  } else if (msg.type === 'candidate') {
    await pc.addIceCandidate(new RTCIceCandidate(msg.candidate));
  }
};
// 4. 监听 ICE 候选并发送给对方(与发起方相同)
pc.onicecandidate = (event) => {
  if (event.candidate) {
    signalingServer.send({ type: 'candidate', candidate: event.candidate });
  }
};

步骤 2:发送和接收数据

一旦 dataChannel.onopen 被触发(两端都触发),就可以随时发送数据。

发送数据:

// 可以发送多种类型
dataChannel.send('Hello');                // 文本
dataChannel.send(new Blob(['blob data'])); // Blob(二进制)
dataChannel.send(new Uint8Array([1,2,3])); // ArrayBuffer / TypedArray

接收数据:

dataChannel.onmessage = (event) => {
  const data = event.data; // 可能是 string 或 Blob 或 ArrayBuffer
  console.log('收到数据:', data);
};

完整示例(同一页面测试)

如果你想在同一个 HTML 页面里测试两端逻辑(一般用于调试),可以这样:

<button id="start">开始连接</button>
<input id="msgInput" placeholder="输入消息" />
<button id="sendBtn">发送</button>
<div id="log"></div>
<script>
const log = (msg) => document.getElementById('log').innerHTML += msg + '<br>';
let pc1, pc2; // 两个对等连接(模拟两端)
let dc1, dc2;
document.getElementById('start').onclick = async () => {
  // 发起方(pc1)
  pc1 = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
  dc1 = pc1.createDataChannel('test');
  dc1.onopen = () => log('DC1 已打开');
  dc1.onmessage = (e) => log('DC1 收到: ' + e.data);
  // 接收方(pc2)
  pc2 = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
  pc2.ondatachannel = (event) => {
    dc2 = event.channel;
    dc2.onopen = () => log('DC2 已打开');
    dc2.onmessage = (e) => log('DC2 收到: ' + e.data);
  };
  // 交换 ICE 候选(本地直接添加)
  pc1.onicecandidate = (e) => e.candidate && pc2.addIceCandidate(e.candidate);
  pc2.onicecandidate = (e) => e.candidate && pc1.addIceCandidate(e.candidate);
  // 创建 Offer -> Answer 交换
  const offer = await pc1.createOffer();
  await pc1.setLocalDescription(offer);
  await pc2.setRemoteDescription(offer);
  const answer = await pc2.createAnswer();
  await pc2.setLocalDescription(answer);
  await pc1.setRemoteDescription(answer);
  log('连接建立完成');
};
document.getElementById('sendBtn').onclick = () => {
  const text = document.getElementById('msgInput').value;
  if (dc1 && dc1.readyState === 'open') {
    dc1.send(text);
  }
};
</script>

常见问题 & 注意事项

  1. 谁创建 DataChannel?
    • 只能由发起 Offer 的一方调用 createDataChannel()
    • 接收方通过 pc.ondatachannel 事件被动获取。
  2. 信令服务器怎么办?

    上述代码只完成了 SDP 和 ICE 交换的逻辑,实际部署需要一个信令服务器(WebSocket、Socket.IO 等)来转发消息。

  3. 数据传输可靠性?
    • ordered: true:保证消息顺序(默认)。
    • maxRetransmits vs maxPacketLifeTime:只能设置一个。
    • protocol: 'sctp':默认协议,支持可靠/半可靠传输。
  4. 连接状态检查:
    • dataChannel.readyStateconnecting -> open -> closing -> closed
    • pc.connectionStatenew -> connecting -> connected -> disconnected -> failed -> closed
  5. 文件传输:
    • 使用 BlobArrayBuffer 传输,注意分片(maxMessageSize 通常约 16KB-64KB,一次发送过大可能失败,需自行分片)。

如果需要更完整的示例(含信令服务器代码),可以告诉我你的信令方案(如 WebSocket、Socket.IO),我可以补充对应的完整代码。

标签: 使用

抱歉,评论功能暂时关闭!