javascript - WebRTC:无法使用 DataChannel 成功完成信令过程

标签 javascript webrtc

我一直在建立 WebRTC session 时遇到问题,我正在尝试尽可能地简化问题。所以我写了一个简单的复制和粘贴示例,您只需将报价/答案粘贴到网络表单中,然后单击提交。

HTML+JS,都在一个文件中,可以在这里找到:http://pastebin.com/Ktmb3mVf

我在本地网络上,因此我删除了 ICE 服务器初始化过程,使这个示例尽可能简单。

以下是我在示例中执行的步骤:

第 1 页

  1. 第 1 页(加载页面),输入 channel 名称(例如 test)并点击 create

  2. 创建一个新的Host对象,调用new PeerConnection()createDataChannel

  3. createOffer 被调用,生成的 offerSDP 被粘贴到 offer 文本区域。

第 2 页

  1. 从第 1 页复制 offerSDP 并粘贴到第 2 页的报价文本区域,点击加入

  2. 创建了新的 Guest 对象,设置了 PeerConnectionondatachannel 处理程序。

  3. setRemoteDescriptionGuest 对象调用,带有 offerSDP 数据。

  4. createAnswer 被调用,结果被粘贴到 answer 文本框。

第 1 页

  1. answerSDP从Page 2复制粘贴到Page 1的answer文本区域,点击submit answer

  2. Host.setRemoteDescription 使用 answerSDP 数据调用。这将创建一个 SessionDescription,然后使用生成的数据调用 peer.setRemoteDescription

这些是示例中执行的步骤,但似乎我遗漏了一些关键的东西。使用 answerSDP 设置 offerer 的 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'

火狐 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

最佳答案

要使 webRTC 客户端能够相互连接,您需要 ICE。虽然此类测试不需要的 STUN 和 TURN 是其中的一部分,但即使没有这些助手,您仍然需要使用 ICE 来告诉另一端连接到哪个 IP/端口/协议(protocol)。

有两种方法可以做到这一点:谷歌的“trickle ice”,SDP(答案/提议)在没有任何 ICE 候选人的情况下传递。然后将它们通过单独的信令层传输并在发现时添加。这加快了连接过程,因为 ICE 需要时间并且可能不需要一些迟到的 ICE 候选人。

经典的方法是等到所有的 ICE 候选人都被收集起来,然后生成已经包含这些的 SDP。

我已经修改了你的最新版本来做到这一点:http://pastebin.com/g2YVvrRd

您还需要等待数据通道/连接可用才能使用它,因此我已将消息的发送移动到 channel 的 onopen 事件。

对原代码的重大改动:

接口(interface)回调已从 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

接口(interface)处理程序 $("#submitAnswer").click() 不再发送消息,而是在 setChannelEvents() 中定义的 onopen 事件中数据通道准备就绪时发送。

channel.onopen = function () {
    console.log('** channel.onopen');
    channel.send('hello world!');
};

关于javascript - WebRTC:无法使用 DataChannel 成功完成信令过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28350963/

相关文章:

webrtc - FreePBX Twilio 出站铃声

javascript - 避免乱七八糟的浏览器死亡

javascript - 如何使用 TinyMCE 上传图像?

javascript - WebRTC session 可以在星形拓扑中使用 html5-JS 客户端吗?

javascript - 网络摄像头权限请求不适用于本地文件

javascript - 如何将 Quickblox 与 angularjs 集成?

javascript - node.js:如何在 forEach 循环中使用异步调用实现路由方法?

javascript - 将 Hoverintent 应用于 Jquery 悬停

javascript - 如何使用 AngularJS ui-router 在 Controller 中构建与 <ui-sref> 相同的 URL 而不是 HTML?

html - 奇怪的WebRTC SinkID问题