javascript - 即使我没有在 peer candidate 中添加 ice candidate,Webrtc Call 也会连接

标签 javascript webrtc

const pc1 = new RTCPeerConnection(null);
const pc2 = new RTCPeerConnection(null);
async function call(){
    const offer = await pc1.createOffer();
    pc1.setLocalDescription(offer);
    pc2.setRemoteDescription(offer);
    const answer = await pc2.createAnswer();
    pc2.setLocalDescription(answer);
    pc1.setRemoteDescription(pc2.localDescription);
}
async function showVideo(){
    const config={audio:true,video:true};
    stream = await navigator.mediaDevices.getUserMedia(config);
    pc1.addStream(stream);
}

这是我的代码的简化版本。

现在在这段代码中,我没有将 icecandidate 添加到对等节点,也没有监听 onicecandidate。但是,如果我调用 call() 两次,我的连接就会建立。

我使用了 iceconnectionstate 更改的事件处理程序,发现当我第一次调用 call 时,它的 iceconnection 状态处于检查状态,当我第二次调用它时,它被调用并且状态变为完成。

所以我想知道即使没有将 icecandidate 添加到另一个对等点,如何启动检查并第二次连接?

最佳答案

四个原因:您的代码中的错误、Chrome 的行为、没有防火墙以及关于 trickle ICE 工作原理的一些事情。

1) 代码中的错误

首先要做的事情:以下设置 pc1.setRemoteDescription(null):

pc2.setLocalDescription(answer);
pc1.setRemoteDescription(pc2.localDescription); // pc2.localDescription == null here

...因为 setLocalDescription 是一个 asynchronous method这不会立即完成。

现在 pc2.localDescription 最终 得到设置,因此您调用调用的第二次 () 它就在那里,协商有效。

要解决此问题,您必须等待 promise使用 awaitthen:

await pc2.setLocalDescription(answer);
pc1.setRemoteDescription(pc2.localDescription); // pc2.localDescription is set!

2) 如果没有 NAT,则不需要 ICE 服务器。

浏览器可以使用“主机”候选者(您机器的 IP)与同一 LAN 上的其他机器或自身进行通信。不需要 ICE 服务器来发现这些。

3) Trickle ICE 是一种优化。

使用 onicecandidate 的单个冰候选者的信号(滴流)是一种旨在加速协商的优化。一旦 setLocalDescription 成功,浏览器的内部 ICE Agent 就会启动,将发现的 ICE 候选插入到 localDescription 本身。等待几秒钟进行谈判,根本不需要滴流:所有 ICE 候选人都将在要约和已传输的答案中。

4) Chrome 中一个有趣的行为。

我怀疑你第二次调用 call() 时,Chrome 的 ICE 代理会记住它上次收集的候选主机,并将它们插入报价和 localDescription 立即,在 setLocalDescription 的成功回调运行完成之前。这可能是一个错误,或者它可能是规范所说的它应该如何工作。无论如何,行为似乎因浏览器 atm 而异,所以我今天不会依赖它。

在SDP中复制/证明ICE的步骤

  1. 运行 this fiddle在 Chrome 和 Firefox 中。
  2. 单击一次 Call! 按钮,然后再单击一次。
  3. 观察 Firefox:你会看到 0 个候选者(输出两次);两次;没有联系。
  4. 观察 Chrome:它与 3 名候选人 第二次 连接,与候选人联系。
  5. 现在取消注释 //await wait(2000);
  6. 两个 浏览器现在连接,2 秒后有 48 个候选项

候选人的实际数量可能因您的系统而异,但行为不应该。

当我在 Firefox 中运行它时,它两次都不会连接,除非我将其修改为等待或滴入候选人)。

浏览器更新: 两个浏览器都有错误:Firefox 是 too restrictive Chrome 是 too lenient从 ICE 故障中恢复。

关于javascript - 即使我没有在 peer candidate 中添加 ice candidate,Webrtc Call 也会连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53410263/

相关文章:

javascript - 如何完全关闭 WebRTC 连接

javascript - 如何导入包含函数的默认导出对象?

javascript - 不支持函数 window.alert

javascript - 我的图片出现在 codepen 上,但没有出现在我的 javascript 网站上

JavaScript : How to write Square bracket in array element

javascript - 如何在 Chrome 中启用屏幕/桌面捕获?

webrtc AEC算法

javascript - WebRTC - 是否可以让浏览器代理视频从源到接收器?

javascript - 为什么我的 WebRTC 连接只能在本地网络上工作?

javascript - 将 javascript 变量添加到 html 错误未定义