Javascript 带有Google通道API的RTCDataChannel
我正试图通过谷歌的p2p通信来进行Javascript 带有Google通道API的RTCDataChannel,javascript,google-app-engine,webrtc,channel-api,rtcdatachannel,Javascript,Google App Engine,Webrtc,Channel Api,Rtcdatachannel,我正试图通过谷歌的p2p通信来进行RTCDataChannel浏览器的信令。它似乎在无声地失败-我无法触发RTCDataChannel.onopen、RTCPeerConnection.onicecandidate、或RTCPeerConnection.ondatachannel事件 客户端JS/HTML: 浏览器控制台: 首先,在数据通道创建的另一端缺少peerConnection.onDataChannel 代码类似于: answerer.ondatachannel = function (
RTCDataChannel
浏览器的信令。它似乎在无声地失败-我无法触发RTCDataChannel.onopen
、RTCPeerConnection.onicecandidate
、或RTCPeerConnection.ondatachannel
事件
客户端JS/HTML:
浏览器控制台:
首先,在数据通道创建的另一端缺少
peerConnection.onDataChannel
代码类似于:
answerer.ondatachannel = function (event) {
answererDataChannel = event.channel;
answererDataChannel.binaryType = 'blob';
setChannelEvents(answererDataChannel, 'answerer');
};
...
function setChannelEvents(channel, channelNameForConsoleOutput) {
channel.onmessage = function (event) {
console.debug(channelNameForConsoleOutput, 'received a message:', event.data);
};
channel.onopen = function () {
channel.send('first text message over SCTP data ports');
};
}
对于完整的代码,您可以检查此对于初学者,您缺少数据通道创建另一侧的
peerConnection.onDataChannel
代码类似于:
answerer.ondatachannel = function (event) {
answererDataChannel = event.channel;
answererDataChannel.binaryType = 'blob';
setChannelEvents(answererDataChannel, 'answerer');
};
...
function setChannelEvents(channel, channelNameForConsoleOutput) {
channel.onmessage = function (event) {
console.debug(channelNameForConsoleOutput, 'received a message:', event.data);
};
channel.onopen = function () {
channel.send('first text message over SCTP data ports');
};
}
对于完整的代码,您可以检查这个经过几个小时的尝试,我能够让我的原始示例在Chrome 40.0.2214.93和Opera 27.0上运行(最新版本)。帮助很大。我没能在Firefox上运行它:
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="/_ah/channel/jsapi"></script>
<script>
$(document).ready(function(){
var IS_CHROME = !!window.webkitRTCPeerConnection,
RTCPeerConnection = window.webkitRTCPeerConnection || mozRTCPeerConnection,
RTCIceCandidate = window.RTCIceCandidate || RTCSessionDescription,
RTCSessionDescription = window.RTCSessionDescription || mozRTCSessionDescription,
SESSION_ID = "123456",
weAreHost,
optionalRtpDataChannels = {
optional: [{RtpDataChannels: true}]
},
mediaConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: false,
OfferToReceiveVideo: false
}
};
// Signaling Channel Object
function SignalingChannel(peerConnection) {
// Setup the signaling channel here
this.peerConnection = peerConnection;
}
function setChannelEvents(dataChannel) {
dataChannel.onmessage = function (event) {
console.log("I got data channel message: ", event.data);
}
dataChannel.onopen = function (event) {
dataChannel.send("######### SUCCESS ######### RTCDataChannel Open!");
}
dataChannel.error = function(event) {
console.log("data channel error:", event)
}
}
function error(e) {
console.log(arguments);
throw new Error(e);
}
SignalingChannel.prototype.send = function(message) {
//console.log("signal send:", message);
var url = "/api/signal/send/";
url += weAreHost ? "client"+SESSION_ID : "host"+SESSION_ID;
$.ajax({
type: "PUT",
url: url,
contentType: "application/json",
data: JSON.stringify(message)
});
};
SignalingChannel.prototype.onmessage = function(message) {
//console.log("signal receive:", message);
var self = this;
if(message.type && message.type === "offer") {
var offer = new RTCSessionDescription(message);
this.peerConnection.setRemoteDescription(offer, function() {
self.peerConnection.createAnswer(function(answer) {
self.peerConnection.setLocalDescription(answer, function() {
self.send(answer);
}, error);
}, error, mediaConstraints);
});
} else if(message.type && message.type === "answer") {
var answer = new RTCSessionDescription(message);
this.peerConnection.setRemoteDescription(answer, function(){
}, error);
} else {
this.peerConnection.addIceCandidate(new RTCIceCandidate(message.candidate));
}
};
function initiateConnection(input) {
weAreHost = input;
// setup signaling mechanism with Google Channel API
var url = "/api/signal/init/";
url += weAreHost ? "host"+SESSION_ID : "client"+SESSION_ID;
$.post(url, "", function(response){
var channel = new goog.appengine.Channel(response.token);
var socket = channel.open();
socket.onerror = error;
var closeSocket = function() {
if(socket) return socket.close();
else return "google socket does not exist"
}
$(window).unload(closeSocket);
window.onbeforeunload = closeSocket;
socket.onopen = function() {
console.log("google socket opened");
// Create a peer connection object
var connection = new RTCPeerConnection({
iceServers: [
{ 'url': (IS_CHROME ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121') }
]
}, optionalRtpDataChannels);
// Initiate a signaling channel between two users
var signalingChannel = new SignalingChannel(connection);
connection.onicecandidate = function (event) {
//console.log("onicecandidate:", event);
if (!event || !event.candidate) return;
signalingChannel.send({candidate:event.candidate});
};
// Effectively set SignalingChannel as google channel socket inbound event handler
socket.onmessage = function(input) {
//console.log("received from google:", input);
var message = $.parseJSON(input.data);
signalingChannel.onmessage(message);
};
// Only one client should initiate the connection, the other client should wait
if(weAreHost) {
connection.ondatachannel = function(event) {
setChannelEvents(event.channel);
}
} else {
// Create client RTCDataChannel
var clientChannel = connection.createDataChannel("my_label", {reliable: false});
setChannelEvents(clientChannel);
// create offer and send to host
connection.createOffer(function (offer) {
connection.setLocalDescription(offer, function() {
signalingChannel.send(offer);
}, error);
}, error, mediaConstraints);
}
};
}, "json").fail(error);
};
// Create a button on the page so only one client initiates the connection.
$("#i-am-host").click(function() {
initiateConnection(true);
});
$("#i-am-client").click(function() {
initiateConnection(false);
});
});
</script>
</head>
<body>
<p id="i-am-host" style="background-color: green;">I AM HOST</p>
<p id="i-am-client" style="background-color: blue;">I AM CLIENT</p>
<br>
<p id="print">PRINT SIGNALING STATE<p>
</body>
</html>
$(文档).ready(函数(){
变量为_CHROME=!!window.webkirtpeerconnection,
RTPEERCONNECTION=window.webkitRTPEERCONNECTION | | mozRTPEERCONNECTION,
RTCIceCandidate=window.RTCIceCandidate | | RTCSessionDescription,
RTCSessionDescription=window.RTCSessionDescription | | mozRTCSessionDescription,
SESSION_ID=“123456”,
weAreHost,
可选RTPDataChannel={
可选:[{RtpDataChannels:true}]
},
媒体约束={
可选:[],
强制性:{
OfferToReceiveAudio:false,
OfferToReceiveVideo:错误
}
};
//信令信道对象
功能信号通道(对等连接){
//在这里设置信令通道
this.peerConnection=peerConnection;
}
函数setChannelEvents(数据通道){
dataChannel.onmessage=函数(事件){
log(“我得到了数据通道消息:”,event.data);
}
dataChannel.onopen=函数(事件){
数据频道。发送(“数据频道开放!”);
}
dataChannel.error=函数(事件){
日志(“数据通道错误:”,事件)
}
}
函数错误(e){
log(参数);
抛出新错误(e);
}
SignalingChannel.prototype.send=函数(消息){
//控制台日志(“信号发送:”,消息);
var url=“/api/signal/send/”;
url+=weAreHost?“客户端”+会话ID:“主机”+会话ID;
$.ajax({
键入:“放置”,
url:url,
contentType:“应用程序/json”,
数据:JSON.stringify(消息)
});
};
SignalingChannel.prototype.onmessage=函数(消息){
//控制台日志(“信号接收:”,消息);
var self=这个;
if(message.type&&message.type==“offer”){
var offer=新的RTCSessionDescription(消息);
this.peerConnection.setRemoteDescription(提供,函数(){
self.peerConnection.createAnswer(函数(应答){
self.peerConnection.setLocalDescription(应答,函数(){
发送(应答);
},错误);
},错误,限制);
});
}else if(message.type&&message.type==“应答”){
var answer=新的RTCSessionDescription(消息);
this.peerConnection.setRemoteDescription(应答,函数(){
},错误);
}否则{
this.peerConnection.addIceCandidate(新的RTCIceCandidate(message.candidate));
}
};
功能启动连接(输入){
weAreHost=输入;
//用googlechannelapi设置信令机制
var url=“/api/signal/init/”;
url+=weAreHost?“主机”+会话ID:“客户端”+会话ID;
$.post(url,“),函数(响应){
var channel=new goog.appengine.channel(response.token);
var socket=channel.open();
socket.onerror=错误;
var closeSocket=函数(){
if(socket)返回socket.close();
否则返回“google套接字不存在”
}
$(窗口)。卸载(closeSocket);
window.onbeforeunload=closeSocket;
socket.onopen=函数(){
log(“谷歌套接字打开”);
//创建对等连接对象
var连接=新的RTPEERCONNECTION({
ICEServer:[
{'url':(是CHROME吗?'stun:stun.l.google.com:19302':'stun:23.21.150.121'))
]
},可选RTPDataChannel);
//启动两个用户之间的信令通道
var信号通道=新信号通道(连接);
connection.onicecandidate=函数(事件){
//console.log(“onicecandidate:,事件”);
如果(!event | |!event.candidate)返回;
send({candidate:event.candidate});
};
//有效地将SignalingChannel设置为google通道套接字入站事件处理程序
socket.onmessage=函数(输入){
//log(“从google接收:”,输入);
var message=$.parseJS
answerer.ondatachannel = function (event) {
answererDataChannel = event.channel;
answererDataChannel.binaryType = 'blob';
setChannelEvents(answererDataChannel, 'answerer');
};
...
function setChannelEvents(channel, channelNameForConsoleOutput) {
channel.onmessage = function (event) {
console.debug(channelNameForConsoleOutput, 'received a message:', event.data);
};
channel.onopen = function () {
channel.send('first text message over SCTP data ports');
};
}
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="/_ah/channel/jsapi"></script>
<script>
$(document).ready(function(){
var IS_CHROME = !!window.webkitRTCPeerConnection,
RTCPeerConnection = window.webkitRTCPeerConnection || mozRTCPeerConnection,
RTCIceCandidate = window.RTCIceCandidate || RTCSessionDescription,
RTCSessionDescription = window.RTCSessionDescription || mozRTCSessionDescription,
SESSION_ID = "123456",
weAreHost,
optionalRtpDataChannels = {
optional: [{RtpDataChannels: true}]
},
mediaConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: false,
OfferToReceiveVideo: false
}
};
// Signaling Channel Object
function SignalingChannel(peerConnection) {
// Setup the signaling channel here
this.peerConnection = peerConnection;
}
function setChannelEvents(dataChannel) {
dataChannel.onmessage = function (event) {
console.log("I got data channel message: ", event.data);
}
dataChannel.onopen = function (event) {
dataChannel.send("######### SUCCESS ######### RTCDataChannel Open!");
}
dataChannel.error = function(event) {
console.log("data channel error:", event)
}
}
function error(e) {
console.log(arguments);
throw new Error(e);
}
SignalingChannel.prototype.send = function(message) {
//console.log("signal send:", message);
var url = "/api/signal/send/";
url += weAreHost ? "client"+SESSION_ID : "host"+SESSION_ID;
$.ajax({
type: "PUT",
url: url,
contentType: "application/json",
data: JSON.stringify(message)
});
};
SignalingChannel.prototype.onmessage = function(message) {
//console.log("signal receive:", message);
var self = this;
if(message.type && message.type === "offer") {
var offer = new RTCSessionDescription(message);
this.peerConnection.setRemoteDescription(offer, function() {
self.peerConnection.createAnswer(function(answer) {
self.peerConnection.setLocalDescription(answer, function() {
self.send(answer);
}, error);
}, error, mediaConstraints);
});
} else if(message.type && message.type === "answer") {
var answer = new RTCSessionDescription(message);
this.peerConnection.setRemoteDescription(answer, function(){
}, error);
} else {
this.peerConnection.addIceCandidate(new RTCIceCandidate(message.candidate));
}
};
function initiateConnection(input) {
weAreHost = input;
// setup signaling mechanism with Google Channel API
var url = "/api/signal/init/";
url += weAreHost ? "host"+SESSION_ID : "client"+SESSION_ID;
$.post(url, "", function(response){
var channel = new goog.appengine.Channel(response.token);
var socket = channel.open();
socket.onerror = error;
var closeSocket = function() {
if(socket) return socket.close();
else return "google socket does not exist"
}
$(window).unload(closeSocket);
window.onbeforeunload = closeSocket;
socket.onopen = function() {
console.log("google socket opened");
// Create a peer connection object
var connection = new RTCPeerConnection({
iceServers: [
{ 'url': (IS_CHROME ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121') }
]
}, optionalRtpDataChannels);
// Initiate a signaling channel between two users
var signalingChannel = new SignalingChannel(connection);
connection.onicecandidate = function (event) {
//console.log("onicecandidate:", event);
if (!event || !event.candidate) return;
signalingChannel.send({candidate:event.candidate});
};
// Effectively set SignalingChannel as google channel socket inbound event handler
socket.onmessage = function(input) {
//console.log("received from google:", input);
var message = $.parseJSON(input.data);
signalingChannel.onmessage(message);
};
// Only one client should initiate the connection, the other client should wait
if(weAreHost) {
connection.ondatachannel = function(event) {
setChannelEvents(event.channel);
}
} else {
// Create client RTCDataChannel
var clientChannel = connection.createDataChannel("my_label", {reliable: false});
setChannelEvents(clientChannel);
// create offer and send to host
connection.createOffer(function (offer) {
connection.setLocalDescription(offer, function() {
signalingChannel.send(offer);
}, error);
}, error, mediaConstraints);
}
};
}, "json").fail(error);
};
// Create a button on the page so only one client initiates the connection.
$("#i-am-host").click(function() {
initiateConnection(true);
});
$("#i-am-client").click(function() {
initiateConnection(false);
});
});
</script>
</head>
<body>
<p id="i-am-host" style="background-color: green;">I AM HOST</p>
<p id="i-am-client" style="background-color: blue;">I AM CLIENT</p>
<br>
<p id="print">PRINT SIGNALING STATE<p>
</body>
</html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="http://cdn.peerjs.com/0.3.9/peer.js"></script>
<script>
$(document).ready(function(){
var SESSION_ID = "1234";
// Create a button on the page so only one client initiates the connection.
$("#i-am-host").click(function() {
var host = new Peer('host'+SESSION_ID, {host: 'my-peerjs.herokuapp.com', port: 80});
host.on("connection", function(conn) {
conn.on('data', function(data) {
console.log(data);
});
});
});
$("#i-am-client").click(function() {
var client = new Peer('client'+SESSION_ID, {host: 'my-peerjs.herokuapp.com', port: 80});
var conn = client.connect('host'+SESSION_ID);
conn.on("open", function(){
conn.send("SUCCESS!!");
});
});
});
</script>
</head>
<body>
<p id="i-am-host" style="background-color: green;">I AM HOST</p>
<p id="i-am-client" style="background-color: blue;">I AM CLIENT</p>
</body>
</html>