问题
I'm trying to implement a mechanism to send textual data (JSON for instance) in from page to page, using javascript at the same machine.
I found some code and wrapped it but it only works at the same page.
At the moment I don't want to use a WwebRTC framework, only 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;
})();
My question is how to pass data between two pages on the same machine using WebRTC?
回答1:
This WebRTC tab chat demo works across tabs or windows in the same browser without a server: https://jsfiddle.net/f5y48hcd/ (I gave up making it work in a code snippet due to a SecurityError.)
Open the fiddle in two windows and try it out. For reference, here's the WebRTC code:
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;
I use this for demoing WebRTC data channels. Note that the secret sauce is the localSocket.js that I wrote for this, which looks like this:
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);
}
};
It basically uses localStorage to simulate web sockets locally between two tabs. If this is all you want to do, then you don't even need WebRTC data channels.
Disclaimer: It's not very robust, and relies on two pages being ready to communicate, so not production-ready by any means.
来源:https://stackoverflow.com/questions/35268660/webrtc-between-two-pages-in-the-same-machine