Javascript 如何在WebRTC对等连接中创建数据通道?

Javascript 如何在WebRTC对等连接中创建数据通道?,javascript,webrtc,Javascript,Webrtc,我正在尝试学习如何创建rtpeerconnection,以便使用DataChannelAPI。以下是我根据自己的理解所做的尝试: var client = new mozRTCPeerConnection; var server = new mozRTCPeerConnection; client.createOffer(function (description) { client.setLocalDescription(description); server.setRem

我正在尝试学习如何创建
rtpeerconnection
,以便使用
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);
        }
    });
});
我不确定出了什么问题,但我假设连接从未建立,因为没有显示任何消息


我从哪里可以了解到更多信息?我已经阅读了教程。

在筛选了大量文章后,我终于让它起作用了:

首先,我们创建对等连接:

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 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);
        });
    });
}
客户创建一个报价:

function offer(description) {
    client.setLocalDescription(description, function () {
        server.setRemoteDescription(description, function () {
            server.createAnswer(answer);
        });
    });
}
服务器接受报价并建立连接:

navigator.mozGetUserMedia(media, callback, errback);

function callback(fakeAudio) {
    server.addStream(fakeAudio);
    client.addStream(fakeAudio);
    client.createOffer(offer);
}

function errback(error) {
    alert(error);
}
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);
        });
    });
}
呸。这需要一段时间才能理解。

我已经演示了如何设置与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;

请注意,您当前需要Chrome每晚启动
——启用数据通道
,使其也能正常工作。

以下是我今天(2014年2月)在Chrome中处理的一系列事件。这是一种简化的情况,即对等方1将视频流传输给对等方2

  • 设置对等方交换消息的方式。(令人遗憾的是,人们如何实现这一点的差异使得不同的WebRTC代码样本变得如此不可通约。但在思想上,以及在您的代码组织中,请尝试将此逻辑与其他逻辑分开。)
  • 在每一侧,为重要的信令消息设置消息处理程序。你可以设置它们,然后不设置它们。有3条核心消息需要处理和发送:
    • 从另一端发送的ice候选者==>使用它调用
      addIceCandidate
    • 提供消息==>
      SetRemoteDescription
      ,然后回答并发送它
    • 应答消息==>
      SetRemoteDescription
  • 在每一侧,创建一个新的peerconnection对象,并为重要事件附加事件处理程序:onicecandidate、onremovestream、onaddstream等。
    • ice候选==>将其发送到另一端
    • 添加的流==>将其附加到视频元素,以便您可以看到它
  • 当两个对等点都存在且所有处理程序都已就位时,对等点1会收到某种触发消息以开始视频捕获(使用
    getUserMedia
    调用)
  • 一旦
    getUserMedia
    成功,我们就有了一个流。在对等1的对等连接对象上调用
    addStream
  • 然后——也只有在那时——第1位提出了一个提议
  • 由于我们在第2步中设置了处理程序,对等方2得到了这个结果并发送了一个答案
  • 与此同时(有些模糊),对等连接对象开始生成ice候选对象。它们在两个对等方之间来回发送并处理(上面的步骤2和步骤3)
  • 由于以下两种情况,流媒体自动以不透明方式启动:
    • 报价/应答交换
    • ice候选人接收、交换和添加

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

    如果我只想创建数据通道来在对等方之间传输数据,为什么我们需要创建假音频流?两个问题:1)不再需要假音频(并且已经很久没有了2)setLocalDescription()和setRemoteDescription()两者都必须按照规范提供成功回调和错误回调。Chrome和FF在这方面都很宽松(尽管我们在FF32中有一个破坏宽松的回归;它可能在32.1中修复,如果不是在33中修复),但它违反了规范。3)现在不需要或使用connectionDataConnection();这是一个旧的暂时的事情,虽然你的答案没有提供代码,我觉得这是迄今为止最好的。我花了几周的时间才理解如何成功连接两个WebRTC客户端,这个答案非常准确。代码很好,但接下来的问题是,您是想使用ajax还是websockets-node.js、Java还是php等。您可以使用这个答案以任何他们喜欢的方式来实现它。