如何判断WebRTC dataChannel.send是否下发?

Rez*_*mya 3 javascript webrtc

我正在尝试使用 WebRTC 编写一个聊天应用程序,我可以使用如下代码通过 dataChannel 发送消息:

const peerConnection = new RTCPeerConnection();

const dataChannel =
  peerConnection.createDataChannel("myLabel", dataChannelOptions);

dataChannel.onerror = (error) => {
  console.log("Data Channel Error:", error);
};

dataChannel.onmessage = (event) => {
  console.log("Got Data Channel Message:", event.data);
};

dataChannel.onopen = () => {
  dataChannel.send("Hello World!");
};

dataChannel.onclose = () => {
  console.log("The Data Channel is Closed");
};
Run Code Online (Sandbox Code Playgroud)

我可以通过dataChannel.send()通道正确发送数据。但我想知道,有没有办法确定发送的消息是否已传递到另一方?

jib*_*jib 5

最简单的答案是:发送回复。

但如果您使用有序可靠的数据通道(这是默认值),您可能不需要这样做。

有序可靠的数据通道

使用其中之一,您可以通过等待bufferedAmount下降来确定消息已发送:

const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
const channel = pc1.createDataChannel("chat");

chat.onkeypress = async e => {
  if (e.keyCode != 13) return;

  const before = channel.bufferedAmount;
  channel.send(chat.value);

  const after = channel.bufferedAmount;
  console.log(`Queued ${after - before} bytes`);

  channel.bufferedAmountLowThreshold = before; // set floor trigger and wait
  await new Promise(r => channel.addEventListener("bufferedamountlow", r));

  console.log(`Sent ${after - channel.bufferedAmount} bytes`);
  chat.value = "";
};

pc2.ondatachannel = e => e.channel.onmessage = e => console.log(`> ${e.data}`);
pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);
pc1.oniceconnectionstatechange = e => console.log(pc1.iceConnectionState);
pc1.onnegotiationneeded = async e => {
  await pc1.setLocalDescription(await pc1.createOffer());
  await pc2.setRemoteDescription(pc1.localDescription);
  await pc2.setLocalDescription(await pc2.createAnswer());
  await pc1.setRemoteDescription(pc2.localDescription);
}
Run Code Online (Sandbox Code Playgroud)
Chat: <input id="chat"><br>
Run Code Online (Sandbox Code Playgroud)

由于通道是可靠的,因此在收到该消息之前它不会放弃发送该消息。

由于通道是有序的,因此在收到此消息之前它不会发送第二条消息。

这使您可以连续发送一堆消息,而无需等待回复。只要bufferedAmount保持关闭,您就知道它正在发送和接收。

简而言之,要确定已收到消息,请发送第二条消息,或让对方发送回复。

不可靠的数据通道

如果您使用不可靠的数据通道,那么发送回复是唯一的方法。但由于无法保证回复会返回,这可能会产生漏报,从而导致接收端出现重复消息。

一方面不可靠,另一方面可靠

使用协商的构造函数参数,可以创建一个在一个方向上不可靠但在另一个方向上可靠的数据通道。这可以用来解决不可靠回复,避免接收(pc2)端出现重复消息。

dc1 = pc1.createDataChannel("chat", {negotiated: true, id: 0, maxRetransmits: 0});
dc2 = pc2.createDataChannel("chat", {negotiated: true, id: 0});
Run Code Online (Sandbox Code Playgroud)