当调用RTCPeerConnection.close()本地连接时,我希望远程连接接收closed connectionstatechange事件。
相反,几秒钟后出现一个disconnected(后跟一个failed)connectionstatechange,这表明我没有正确关闭连接?
是否需要执行任何其他步骤来关闭RTCPeerConnection(例如,我需要删除任何轨道吗?)。我期望发送一个closed而不是事件是否正确 - 并且这种情况应该在几秒钟内发生?failed
检测其他对等方关闭连接的最佳方法是始终与您的连接协商 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 workaroundRun 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)