【问题标题】:How to create data channel in WebRTC peer connection?如何在 WebRTC 对等连接中创建数据通道?
【发布时间】:2016-03-15 17:33:35
【问题描述】:

我正在尝试学习如何创建RTCPeerConnection,以便可以使用DataChannel API。根据我的理解,这是我尝试过的:

var client = new mozRTCPeerConnection;
var server = new mozRTCPeerConnection;

client.createOffer(function (description) {
    client.setLocalDescription(description);
    server.setRemoteDescription(description);

    server.createAnswer(function (description) {
        server.setLocalDescription(description);
        client.setRemoteDescription(description);

        var clientChannel = client.createDataChannel("chat");
        var serverChannel = server.createDataChannel("chat");

        clientChannel.onmessage = serverChannel.onmessage = onmessage;

        clientChannel.send("Hello Server!");
        serverChannel.send("Hello Client!");

        function onmessage(event) {
            alert(event.data);
        }
    });
});

我不确定出了什么问题,但我假设连接从未建立,因为没有显示任何消息。

我在哪里可以了解更多信息?我已经阅读了Getting Started with WebRTC - HTML5 Rocks 教程。

【问题讨论】:

    标签: javascript webrtc


    【解决方案1】:

    查了很多文章终于搞定了:http://jsfiddle.net/LcQzV/

    首先我们创建对等连接:

    var media = {};
    media.fake = media.audio = true;
    var client = new mozRTCPeerConnection;
    var server = new mozRTCPeerConnection;
    

    当客户端连接到服务器时,它必须打开一个数据通道:

    client.onconnection = function () {
        var channel = client.createDataChannel("chat", {});
    
        channel.onmessage = function (event) {
            alert("Server: " + event.data);
        };
    
        channel.onopen = function () {
            channel.send("Hello Server!");
        };
    };
    

    当客户端创建数据通道时,服务器可能会响应:

    server.ondatachannel = function (channel) {
        channel.onmessage = function (event) {
            alert("Client: " + event.data);
        };
    
        channel.onopen = function () {
            channel.send("Hello Client!");
        };
    };
    

    我们需要给客户端和服务端添加一个假的音频流来建立连接:

    navigator.mozGetUserMedia(media, callback, errback);
    
    function callback(fakeAudio) {
        server.addStream(fakeAudio);
        client.addStream(fakeAudio);
        client.createOffer(offer);
    }
    
    function errback(error) {
        alert(error);
    }
    

    客户创建报价:

    function offer(description) {
        client.setLocalDescription(description, function () {
            server.setRemoteDescription(description, function () {
                server.createAnswer(answer);
            });
        });
    }
    

    服务器接受报价并建立连接:

    function answer(description) {
        server.setLocalDescription(description, function () {
            client.setRemoteDescription(description, function () {
                var port1 = Date.now();
                var port2 = port1 + 1;
    
                client.connectDataConnection(port1, port2);
                server.connectDataConnection(port2, port1);
            });
        });
    }
    

    呸。这需要一段时间才能理解。

    【讨论】:

    • 如果我想创建数据通道只是为了在对等点之间传输数据,为什么我们需要创建假音频流?
    • 几个问题:1) 不再需要假音频(现在已经很久没有了 2) setLocalDescription() 和 setRemoteDescription() 都必须成功和 i> 根据规范提供的错误回调。 Chrome 和 FF 对此很宽容(尽管我们在 FF32 中有一个回归,打破了宽容;它可能在 32.1 或 33 中修复),但它违反了规范。 3) connectionDataConnection() 现在不需要或使用;这在 FF 中是一件古老的临时事情
    【解决方案2】:

    我有 posted a gist,它显示了设置数据连接,与 Chrome 和 Firefox 兼容。

    主要区别在于,在 FF 中您必须等到建立连接,而在 Chrome 中恰恰相反:您似乎需要在发送任何优惠之前创建数据连接来回:

    var pc1 = new RTCPeerConnection(cfg, con);
    if (!pc1.connectDataConnection) setupDC1();    // Chrome...Firefox defers per other answer
    

    另一个区别是 Chrome 将一个事件对象传递给.ondatachannel,而 FF 只传递一个原始通道:

    pc2.ondatachannel = function (e) {
        var datachannel = e.channel || e;
    

    请注意,您目前需要以 --enable-data-channels 开头的 Chrome Nightly 才能正常工作。

    【讨论】:

      【解决方案3】:

      这是我今天(2014 年 2 月)在 Chrome 中工作的一系列事件。这是为了简化情况,其中对等方 1 将视频流传输到对等方 2。

      1. 为对等方设置某种方式来交换消息。 (可悲的是,人们实现这一点的方式的差异使得不同的 WebRTC 代码示例如此不可通约。但在精神上以及在您的代码组织中,请尝试将此逻辑与其他逻辑区分开来。)
      2. 在每一侧,为重要的信令消息设置消息处理程序。您可以设置它们并保留它们。有 3 个核心消息需要处理和发送:
        • 对方派来的冰候选者 ==> 用它打电话给addIceCandidate
        • 提供消息 ==> SetRemoteDescription 并附上,然后回复并发送
        • 回复消息 ===> SetRemoteDescription 与它
      3. 在每一侧,创建一个新的 peerconnection 对象并将事件处理程序附加到它以处理重要事件:onicecandidate、onremovestream、onaddstream 等。
        • ice 候选 ===> 发送到另一边
        • 已添加流 ===> 将其附加到视频元素,以便您查看
      4. 当两个对等点都存在并且所有处理程序都到位时,对等点 1 会收到某种触发消息以开始视频捕获(使用 getUserMedia 调用)
      5. 一旦getUserMedia 成功,我们就有了一个流。在 peer 1 的 peer 连接对象上调用addStream。
      6. 然后 - 并且只有这样 - 对等方 1 提出要约
      7. 由于我们在第 2 步中设置的处理程序,对等方 2 收到此信息并发送答案
      8. 与此同时(并且有些模糊),对等连接对象开始生成候选冰。它们在两个对等点之间来回发送并进行处理(上面的第 2 步和第 3 步)
      9. 由于以下两个条件,流式传输会自行开始,不透明:
        • 提供/回答交换
        • ice 候选人收到、交换和添加

      在第 9 步之后我还没有找到添加视频的方法。当我想更改某些内容时,我会返回第 3 步。

      【讨论】:

      • 虽然您的答案没有提供代码,但我觉得它是迄今为止最好的。我花了几个星期才了解如何成功连接两个 WebRTC 客户端,这个答案是正确的。代码很好,但接下来是您是否要使用 ajax 或 websockets 的问题 - node.js、Java 或 php 等。人们可以使用这个答案以任何他们喜欢的方式来做。
      猜你喜欢
      • 1970-01-01
      • 2017-08-25
      • 1970-01-01
      • 1970-01-01
      • 2015-02-01
      • 2018-10-12
      • 2022-01-18
      • 2018-06-27
      • 1970-01-01
      相关资源
      最近更新 更多