WebRTC在同一台机器中的两个页面之间

时间:2016-02-08 11:33:38

标签: javascript ipc webrtc communication

我正在尝试使用相同计算机上的javascript,在页面之间实现发送文本数据(例如JSON)的机制。
我发现了一些代码并将其包装但它只能在同一页面上运行。
目前我不想使用WwebRTC框架,只需要使用adapter.js。

//Must include adapter.js before

var WebRTCManager = (function () {

    'use strict';

    //Ctor
    function WebRTCManagerFn() {

      console.log('WebRTCManagerFn ctor reached');

      this._events = {};

      this._localConnection = null
      this._remoteConnection = null;
      this._sendChannel = null;
      this._receiveChannel = null;
    }

    WebRTCManagerFn.prototype.addEventListener = function (name, handler)        {
      if (this._events.hasOwnProperty(name))
          this._events[name].push(handler);
      else
          this._events[name] = [handler];
    };

    WebRTCManagerFn.prototype._fireEvent = function (name, event) {
       if (!this._events.hasOwnProperty(name))
          return;

       if (!event)
          event = {};

       var listeners = this._events[name], l = listeners.length;
       for (var i = 0; i < l; i++) {
          listeners[i].call(null, event);
       }
    };

WebRTCManagerFn.prototype.createConnection = function () {
    var servers = null;
    var pcConstraint = null;
    var dataConstraint = null;

    console.log('Using SCTP based data channels');

    // SCTP is supported from Chrome 31 and is supported in FF.
    // No need to pass DTLS constraint as it is on by default in Chrome 31.
    // For SCTP, reliable and ordered is true by default.
    // Add localConnection to global scope to make it visible
    // from the browser console.
    window.localConnection = this._localConnection =
        new RTCPeerConnection(servers, pcConstraint);
    console.log('Created local peer connection object localConnection');

    this._sendChannel = this._localConnection.createDataChannel('sendDataChannel',
            dataConstraint);
    console.log('Created send data channel');
    this._localConnection.onicecandidate = this._localIceCallback.bind(this);
    this._sendChannel.onopen = this._onSendChannelStateChange.bind(this);
    this._sendChannel.onclose = this._onSendChannelStateChange.bind(this);

    // Add remoteConnection to global scope to make it visible
    // from the browser console.
    window.remoteConnection = this._remoteConnection =
        new RTCPeerConnection(servers, pcConstraint);
    console.log('Created remote peer connection object remoteConnection');
    this._remoteConnection.onicecandidate = this._remoteIceCallback.bind(this);
    this._remoteConnection.ondatachannel = this._receiveChannelCallback.bind(this);

    this._localConnection.createOffer(this._gotOfferFromLocalConnection.bind(this), this._onCreateSessionDescriptionError.bind(this));
}

WebRTCManagerFn.prototype._onCreateSessionDescriptionError = function (error) {
    console.log('Failed to create session description: ' + error.toString());
}

WebRTCManagerFn.prototype.sendMessage = function (msgText) {
    var msg = new Message(msgText);

    // Send the msg object as a JSON-formatted string.
    var data = JSON.stringify(msg);
    this._sendChannel.send(data);

    console.log('Sent Data: ' + data);
}

WebRTCManagerFn.prototype.closeDataChannels = function () {
    console.log('Closing data channels');
    this._sendChannel.close();
    console.log('Closed data channel with label: ' + this._sendChannel.label);
    this._receiveChannel.close();
    console.log('Closed data channel with label: ' + this._receiveChannel.label);
    this._localConnection.close();
    this._remoteConnection.close();
    this._localConnection = null;
    this._remoteConnection = null;
    console.log('Closed peer connections');
}

WebRTCManagerFn.prototype._gotOfferFromLocalConnection = function (desc) {
    console.log('reached _gotOfferFromLocalConnection');
    if (this && this._localConnection != 'undefined' && this._remoteConnection != 'undefined') {
        this._localConnection.setLocalDescription(desc);
        console.log('Offer from localConnection \n' + desc.sdp);
        this._remoteConnection.setRemoteDescription(desc);
        this._remoteConnection.createAnswer(this._gotAnswerFromRemoteConnection.bind(this),
            this._onCreateSessionDescriptionError.bind(this));
    }
}

WebRTCManagerFn.prototype._gotAnswerFromRemoteConnection = function (desc) {
    console.log('reached _gotAnswerFromRemoteConnection');
    if (this && this._localConnection != 'undefined' && this._remoteConnection != 'undefined') {
        this._remoteConnection.setLocalDescription(desc);
        console.log('Answer from remoteConnection \n' + desc.sdp);
        this._localConnection.setRemoteDescription(desc);
    }
}

WebRTCManagerFn.prototype._localIceCallback = function (event) {
    console.log('local ice callback');
    if (event.candidate) {
        this._remoteConnection.addIceCandidate(event.candidate,
            this._onAddIceCandidateSuccess.bind(this), this._onAddIceCandidateError.bind(this));
        console.log('Local ICE candidate: \n' + event.candidate.candidate);
    }
}

WebRTCManagerFn.prototype._remoteIceCallback = function (event) {
    console.log('remote ice callback');
    if (event.candidate) {
        this._localConnection.addIceCandidate(event.candidate,
            this._onAddIceCandidateSuccess.bind(this), this._onAddIceCandidateError.bind(this));
        console.log('Remote ICE candidate: \n ' + event.candidate.candidate);
    }
}

WebRTCManagerFn.prototype._onAddIceCandidateSuccess = function (evt) {
    debugger;
    console.log('AddIceCandidate success. evt: '+ evt);
}

WebRTCManagerFn.prototype._onAddIceCandidateError = function (error) {
    console.log('Failed to add Ice Candidate: ' + error.toString());
}

WebRTCManagerFn.prototype._receiveChannelCallback = function (event) {
    console.log('Receive Channel Callback');
    this._receiveChannel = event.channel;
    this._receiveChannel.onmessage = this._onReceiveMessageCallback.bind(this);
    this._receiveChannel.onopen = this._onReceiveChannelStateChange.bind(this);
    this._receiveChannel.onclose = this._onReceiveChannelStateChange.bind(this);
}

WebRTCManagerFn.prototype._onReceiveMessageCallback = function (event) {
    console.log('Received Message: ' + event.data);
    console.log('Received Message this is: ' + this);

    var msgObj = JSON.parse(event.data);

    this._fireEvent("messageRecieved", {
        details: {
            msg: msgObj
        }
    });
}

WebRTCManagerFn.prototype._onSendChannelStateChange = function () {
    console.log('_onSendChannelStateChange');
    var readyState = this._sendChannel.readyState;
    console.log('Send channel state is: ' + readyState);
}

WebRTCManagerFn.prototype._onReceiveChannelStateChange = function () {
    var readyState = this._receiveChannel.readyState;
    console.log('Receive channel state is: ' + readyState);
}

return WebRTCManagerFn;
})();

我的问题是如何使用WebRTC在同一台计算机上的两个页面之间传递数据

1 个答案:

答案 0 :(得分:7)

此WebRTC标签聊天演示可在不使用服务器的同一浏览器中跨选项卡或窗口工作:https://jsfiddle.net/f5y48hcd/(由于安全错误,我放弃了使其在代码段中运行。)

在两个窗口中打开小提琴并尝试一下。作为参考,这里是WebRTC代码:

var pc = new RTCPeerConnection(), dc, enterPressed = e => e.keyCode == 13;

var connect = () => init(dc = pc.createDataChannel("chat"));
pc.ondatachannel = e => init(dc = e.channel);

var init = dc => {
  dc.onopen = e => (dc.send("Hi!"), chat.select());
  dc.onclose = e => log("Bye!");
  dc.onmessage = e => log(e.data);
};

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

var sc = new localSocket(), send = obj => sc.send(JSON.stringify(obj));
var incoming = msg => msg.sdp &&
  pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
  .then(() => pc.signalingState == "stable" || pc.createAnswer()
    .then(answer => pc.setLocalDescription(answer))
    .then(() => send({ sdp: pc.localDescription })))
  .catch(log) || msg.candidate &&
  pc.addIceCandidate(new RTCIceCandidate(msg.candidate)).catch(log);
sc.onmessage = e => incoming(JSON.parse(e.data));

pc.oniceconnectionstatechange = e => log(pc.iceConnectionState);
pc.onicecandidate = e => send({ candidate: e.candidate });
pc.onnegotiationneeded = e => pc.createOffer()
  .then(offer => pc.setLocalDescription(offer))
  .then(() => send({ sdp: pc.localDescription }))
  .catch(log);

var log = msg => div.innerHTML += "<br>" + msg;

我用它来演示WebRTC数据通道。请注意秘密酱是我为此写的localSocket.js,如下所示:

function localSocket() {
  localStorage.a = localStorage.b = JSON.stringify([]);
  this.index = 0;
  this.interval = setInterval(() => {
    if (!this.in) {
      if (!JSON.parse(localStorage.a).length) return;
      this.in = "a"; this.out = "b";
    }
    var arr = JSON.parse(localStorage[this.in]);
    if (arr.length <= this.index) return;
    if (this.onmessage) this.onmessage({ data: arr[this.index] });
    this.index++;
  }, 200);
  setTimeout(() => this.onopen && this.onopen({}));
}
localSocket.prototype = {
  send: function(msg) {
    if (!this.out) {
      this.out = "a"; this.in = "b";
    }
    var arr = JSON.parse(localStorage[this.out]);
    arr.push(msg);
    localStorage[this.out] = JSON.stringify(arr);
  },
  close: function() {
    clearInterval(this.interval);
  }
};

它基本上使用localStorage在两个选项卡之间本地模拟Web套接字。如果您只想做这件事,那么您甚至不需要WebRTC数据通道。

免责声明:它不是非常强大,并且依赖于两页准备好进行通信,因此无论如何都不能为生产做好准备。