我一直无法建立WebRTC会话,并且正在尽可能地简化问题。所以我写了一个简单的副本&粘贴示例,您只需将商品/答案粘贴到网络表单中,然后单击“提交”。
HTML + JS,在一个文件中,可以在这里找到:http://pastebin.com/Ktmb3mVf
我在本地网络上,因此正在删除ICE服务器初始化过程,以使此示例尽可能简单。
以下是我在示例中执行的步骤:
Page 1
第1页(加载页面),输入频道名称(例如test
)并点击create
。
创建了一个新的Host
对象,并调用了new PeerConnection()
和createDataChannel
。
createOffer
被调用,生成的offerSDP
被粘贴到offer
textarea。
第2页
从第1页复制offerSDP
并粘贴到第2页的商品textarea,点击join
。
创建了新的Guest
对象,PeerConnection
并设置了ondatachannel
处理程序。
setRemoteDescription
数据为Guest
对象调用 offerSDP
。
createAnswer
被调用,结果将粘贴到answer
textarea框中。
Page 1
从{2}复制answerSDP
并粘贴到第1页的answer
文本区域,点击submit answer
。
Host.setRemoteDescription
数据调用 answerSDP
。这会创建SessionDescription
,然后使用生成的数据调用peer.setRemoteDescription
。
这些是示例中执行的步骤,但似乎我遗漏了一些关键的东西。在使用answerSDP
设置提议者的remoteDescription之后,我尝试在dataChannel
上发送测试消息:
Chrome 40
"-- complete"
> host.dataChannel.send('hello world');
VM1387:2 Uncaught DOMException: Failed to execute 'send' on 'RTCDataChannel': RTCDataChannel.readyState is not 'open'
Firefox 35
"-- complete"
ICE failed, see about:webrtc for more details
> host.dataChannel.send('hello world');
InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
我还有一个更复杂的演示操作,有一个WebSocket信令服务器和列出的ICE候选人,但是得到了同样的错误。所以我希望这种简化有助于追踪问题。
同样,单文件代码链接:http://pastebin.com/Ktmb3mVf
答案 0 :(得分:1)
要使webRTC客户端能够相互连接,您需要ICE。虽然您不需要进行此类测试的STUN和TURN,但即使没有这些帮助程序,您仍需要使用ICE告诉另一端要连接的IP /端口/协议。
有两种方法可以做到这一点:谷歌的“涓涓细流”,SDP(答案/报价)在没有任何ICE候选人的情况下被传递。然后将它们通过单独的信号层传输并在发现它们时添加。这加快了连接过程,因为ICE需要时间,可能不需要一些已故的ICE候选者。
经典的方法是等到所有ICE候选人都被收集起来,然后生成已包含这些候选人的SDP。
我已修改您的最新版本:http://pastebin.com/g2YVvrRd
您还需要等待数据通道/连接变为可用才能使用它,因此我已将消息发送到通道onopen事件。
对原始代码的重大更改:
接口回调已从Host.prototype.createOffer和Guest.prototype.createAnswer中删除,而是将提供的回调函数附加到相应的对象以供以后使用。
self.cb = cb;
Host和Guest都为PeerConnection添加了一个ICE处理程序:
var self = this;
this.peer.onicecandidate = function (event) {
// This event is called for every discovered ICE candidate.
// If this was trickle ICE, you'd pass them on here.
// An event without an actual candidate signals the end of the
// ICE collection process, which is what we need for classic ICE.
if (!event.candidate) {
// We fetch the up to date description from the PeerConnection
// It now contains lines with the available ICE candidates
self.offer = self.peer.localDescription;
// Now we move on to the deferred callback function
self.cb(self.offer);
}
}
对于来宾self.offer变为self.answer
接口处理程序$(“#submitAnswer”)。click()不再发送消息,而是在setChannelEvents()中定义的onopen事件中数据通道就绪时发送。
channel.onopen = function () {
console.log('** channel.onopen');
channel.send('hello world!');
};