【问题标题】:How to start a basic WebRTC data channel?如何启动一个基本的 WebRTC 数据通道?
【发布时间】:2015-08-03 09:04:44
【问题描述】:

如何启动一个基本的WebRTC数据通道?

这是我到目前为止所拥有的,但它似乎甚至没有尝试连接。我确定我只是缺少一些基本的东西。

var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.msRTCPeerConnection;

var peerConnection = new RTCPeerConnection({
    iceServers: [
        {url: 'stun:stun1.l.google.com:19302'},
        {url: 'stun:stun2.l.google.com:19302'},
        {url: 'stun:stun3.l.google.com:19302'},
        {url: 'stun:stun4.l.google.com:19302'},
    ]
});
peerConnection.ondatachannel  = function () {
    console.log('peerConnection.ondatachannel');
};
peerConnection.onicecandidate = function () {
    console.log('peerConnection.onicecandidate');
};

var dataChannel = peerConnection.createDataChannel('myLabel', {
});

dataChannel.onerror = function (error) {
    console.log('dataChannel.onerror');
};

dataChannel.onmessage = function (event) {
    console.log('dataChannel.onmessage');
};

dataChannel.onopen = function () {
    console.log('dataChannel.onopen');
    dataChannel.send('Hello World!');
};

dataChannel.onclose = function () {
    console.log('dataChannel.onclose');
};
console.log(peerConnection, dataChannel);

【问题讨论】:

  • 它没有尝试连接,因为您的代码没有做任何连接。您必须与另一个同行发起提议/答案交换。你用什么发信号?是什么发起了对另一个连接的调用?
  • @xdumaine 是的,我有点不确定,关于如何做到这一点的任何信息?是否可以在没有服务器(即 p2p)的情况下做到这一点?

标签: javascript webrtc


【解决方案1】:

WebRTC 假设您有办法向您希望联系的任何人发送信号(向其发送报价字符串并从其接收答案字符串)。没有服务器,你会怎么做?

为了说明,这里有一些代码可以做所有事情(在 Firefox 和 Chrome 45 中工作):

var config = { iceServers: [{ urls: "stun:stun.l.google.com:19302" }]};
var dc, pc = new RTCPeerConnection(config);
pc.ondatachannel = e => {
  dc = e.channel;
  dc.onopen = e => (log("Chat!"), chat.select());
  dc.onmessage = e => log(e.data);
}

function createOffer() {
  button.disabled = true;
  pc.ondatachannel({ channel: pc.createDataChannel("chat") });
  pc.createOffer().then(d => pc.setLocalDescription(d)).catch(failed);
  pc.onicecandidate = e => {
    if (e.candidate) return;
    offer.value = pc.localDescription.sdp;
    offer.select();
    answer.placeholder = "Paste answer here";
  };
};

offer.onkeypress = e => {
  if (e.keyCode != 13 || pc.signalingState != "stable") return;
  button.disabled = offer.disabled = true;
  var obj = { type:"offer", sdp:offer.value };
  pc.setRemoteDescription(new RTCSessionDescription(obj))
  .then(() => pc.createAnswer()).then(d => pc.setLocalDescription(d))
  .catch(failed);
  pc.onicecandidate = e => {
    if (e.candidate) return;
    answer.focus();
    answer.value = pc.localDescription.sdp;
    answer.select();
  };
};

answer.onkeypress = e => {
  if (e.keyCode != 13 || pc.signalingState != "have-local-offer") return;
  answer.disabled = true;
  var obj = { type:"answer", sdp:answer.value };
  pc.setRemoteDescription(new RTCSessionDescription(obj)).catch(failed);
};

chat.onkeypress = e => {
  if (e.keyCode != 13) return;
  dc.send(chat.value);
  log(chat.value);
  chat.value = "";
};

var log = msg => div.innerHTML += "<p>" + msg + "</p>";
var failed = e => log(e + ", line " + e.lineNumber);
<script src="https://rawgit.com/webrtc/adapter/master/adapter.js"></script>
<button id="button" onclick="createOffer()">Offer:</button>
<textarea id="offer" placeholder="Paste offer here"></textarea><br>
Answer: <textarea id="answer"></textarea><br><div id="div"></div>
Chat: <input id="chat"></input><br>

在第二个标签页中打开此页面,您可以从一个标签页聊天到另一个标签页(或世界各地的另一台机器)。糟糕的是你必须自己去那里拿到offer:

  • 按下选项卡 A 中的 Offer 按钮(仅限)并等待 1-20 秒,直到您看到报价文本,
  • 将报价文本从选项卡 A 复制粘贴到选项卡 B,然后点击 Enter
  • 将出现的答案文本从选项卡 B 复制粘贴到选项卡 A,然后点击 Enter

您现在应该可以在标签之间聊天,无需服务器。

如您所见,这是一种低于标准的体验,这就是为什么您需要一些基本的 websocket 服务器来在 A 和 B 之间传递提议/答案(以及如果您想快速连接,还需要涓涓冰候选),让事情开始。建立连接后,您可以为此使用数据通道,但需要做一些额外的工作。

【讨论】:

  • 不错的答案,如果你能充实一点,整理一下,让它跨浏览器工作,我会赏金你 500 代表。
  • 我已经使用adapter.js polyfill 更新了在 Chrome 45 中工作的答案。希望有帮助!你的提议很慷慨,但我的兴趣是推广标准,所以我不愿意使用遗留回调或丢失箭头函数,因为我发现这使得 WebRTC 示例非常难以阅读。 - 如果您对差异有任何疑问,请不要犹豫!
  • @jib 下面这行有什么意义:pc.ondatachannel({ channel: pc.createDataChannel("chat") });?在其他示例中,ondatachannel 总是用作回调?用对象调用它有什么意义?
  • @Lars 只是在一侧直接调用回调;一种在两端运行相同数据通道初始化代码的非常聪明的方法,因为默认情况下 API 是不对称的。在现代代码中,我建议改用更对称和声明性的 negotiated API:jsfiddle.net/jib1/ovbc1uzf
猜你喜欢
  • 1970-01-01
  • 2019-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-24
  • 2014-01-08
  • 1970-01-01
相关资源
最近更新 更多