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使用 await
或 then
:
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的步骤
- 运行 this fiddle在 Chrome 和 Firefox 中。
- 单击一次
Call!
按钮,然后再单击一次。 - 观察 Firefox:你会看到
0 个候选者
(输出两次);两次;没有联系。 - 观察 Chrome:它与
3 名候选人
第二次 连接,与候选人联系。 - 现在取消注释
//await wait(2000);
- 两个 浏览器现在连接,2 秒后有
4
或8 个候选项
。
候选人的实际数量可能因您的系统而异,但行为不应该。
当我在 Firefox 中运行它时,它两次都不会连接,除非我将其修改为等待或滴入候选人)。
浏览器更新: 两个浏览器都有错误:Firefox 是 too restrictive Chrome 是 too lenient从 ICE 故障中恢复。
关于javascript - 即使我没有在 peer candidate 中添加 ice candidate,Webrtc Call 也会连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53410263/