为什么调用`RTCPeerConnection.close()`不发送`close`事件?

Cro*_*ssy 5 javascript webrtc

当调用RTCPeerConnection.close()本地连接时,我希望远程连接接收closed connectionstatechange事件。

相反,几秒钟后出现一个disconnected(后跟一个failedconnectionstatechange,这表明我没有正确关闭连接?

是否需要执行任何其他步骤来关闭RTCPeerConnection(例如,我需要删除任何轨道吗?)。我期望发送一个closed而不是事件是否正确 - 并且这种情况应该在几秒钟内发生?failed

jib*_*jib 2

检测其他对等方关闭连接的最佳方法是始终与您的连接协商 SCTP 数据通道并侦听数据通道的关闭事件:

const pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();

const dc1 = pc1.createDataChannel("");
dc1.onopen = () => console.log("open");
dc1.onclose = () => console.log("remote closed");
button.onclick = () => pc2.close();

pc1.onnegotiationneeded = async () => {
  await pc1.setLocalDescription(await pc1.createOffer());
  await pc2.setRemoteDescription(pc1.localDescription);
  await pc2.setLocalDescription(await pc2.createAnswer());
  await pc1.setRemoteDescription(pc2.localDescription);
};
pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);
pc2.oniceconnectionstatechange = () => console.log(pc2.iceConnectionState);

pc2.ondatachannel = e => window.keepalive = e.channel; // Firefox GC workaround
Run Code Online (Sandbox Code Playgroud)
<button id="button">Close remote</button>
Run Code Online (Sandbox Code Playgroud)

当远程 JS 显式调用或远程用户关闭浏览器选项卡或导航离开时,远程浏览器会通过线路发送SCTP ABORTpc2.close()块,即他们有意关闭连接,这与任何网络丢失不同。

这是协商数据通道的优点之一,没有它,对等连接就没有其他直接线路信号来有意关闭连接。但有了它就完全可以了。

这是即时的(点对点)并且比使用信令消息更可靠,信令消息可能无法涵盖远程用户在不编写额外 JS 的情况下关闭选项卡的情况。

选项卡关闭演示

要演示远程选项卡关闭的检测,请在同一浏览器的两个窗口中打开此小提琴Connect,然后单击其中一个窗口中的按钮。现在关闭任一窗口并在另一个窗口中查找消息“远程已关闭”。它使用 localStorage hack 来发送信号,但如果你查看 JavaScript,你会发现该消息来自数据通道:

dc.onclose = () => console.log("remote closed");
Run Code Online (Sandbox Code Playgroud)