我尝试关注this example by Dan Ristic RTCDataChannel
与Google Channel API进行RTCDataChannel.onopen
浏览器p2p通信,以发送信号。它似乎在默默地失败 - 我无法触发RTCPeerConnection.onicecandidate
,RTCPeerConnection.ondatachannel
或<html>
<head>
<script src="https://code.jquery.com/jquery-1.11.2.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 = "12345",
weAreHost,
optionalRtpDataChannels = {
optional: [{RtpDataChannels: true}]
},
mediaConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: false, // Hmm!!
OfferToReceiveVideo: false // Hmm!!
}
};
// 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("RTCDataChannel Open!");
}
dataChannel.error = function(event) {
console.log("data channel error:", event)
}
}
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);
// If we get a sdp we have to sign and return it
if (message.sdp != null) {
var that = this;
this.peerConnection.setRemoteDescription(new RTCSessionDescription(message), function () {
that.peerConnection.createAnswer(function (description) {
that.send(description);
}, null, mediaConstraints);
});
} 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 = function(){console.log(arguments);};
socket.onclose = function(){console.log(arguments);};
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);
connection.createOffer(function (description) {
signalingChannel.send(description);
}, function(error){
console.log(error);
}, mediaConstraints);
}
};
}, "json");
};
// 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>
</body>
</html>
事件。
from google.appengine.api import channel
from django.shortcuts import render
from django.http import HttpResponse
import json
def init(request, browser_id):
token = channel.create_channel(browser_id);
return HttpResponse(json.dumps({'token':token}))
def send(request, browser_id):
channel.send_message(browser_id, request.body)
return HttpResponse()
[HOST]
received from google:
Object {data: "{"sdp":"v=0\r\no=- 6804947085651458452 2 IN IP4 12…5000 webrtc-datachannel 1024\r\n","type":"offer"}"}
test.html:34
signal receive:
Object {sdp: "v=0
↵o=- 6804947085651458452 2 IN IP4 127.0.0.1
↵s…id:data
↵a=sctpmap:5000 webrtc-datachannel 1024
↵", type: "offer"}
test.html:22
signal send:
RTCSessionDescription {sdp: "v=0
↵o=- 600524556593905006 2 IN IP4 127.0.0.1
↵s=…id:data
↵a=sctpmap:5000 webrtc-datachannel 1024
↵", type: "answer"}
[CLIENT]
signal send:
RTCSessionDescription {sdp: "v=0
↵o=- 6804947085651458452 2 IN IP4 127.0.0.1
↵s…id:data
↵a=sctpmap:5000 webrtc-datachannel 1024
↵", type: "offer"}
test.html:82
received from google:
Object {data: "{"sdp":"v=0\r\no=- 600524556593905006 2 IN IP4 127…000 webrtc-datachannel 1024\r\n","type":"answer"}"}
test.html:34
signal receive: Object {sdp: "v=0
↵o=- 600524556593905006 2 IN IP4 127.0.0.1
↵s=…id:data
↵a=sctpmap:5000 webrtc-datachannel 1024
↵", type: "answer"}
{{1}}
答案 0 :(得分:4)
Firefox不支持(也绝不会)支持RtpDataChannels。它仅支持符合规范(和更高级)的SCTP数据通道。删除可选约束应该将您切换到它们而不需要进行其他更改。
您的SDP似乎有sctp线,这有点奇怪。 http://googlechrome.github.io/webrtc/samples/web/content/datachannel/上的Google示例 使用rtp数据通道时不会。
答案 1 :(得分:1)
对于初学者,您在数据通道创建的另一侧缺少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');
};
}
完整代码,您可以查看此link
答案 2 :(得分:0)
经过几个小时的尝试,我能够将我的原始示例用于Chrome 40.0.2214.93和Opera 27.0(撰写本文时的最新版本)。 why doesn't “onicecandidate” work?帮了很多忙。我没有运气在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>
我决定和PeerJS一起使用免费的Heroku服务器进行信号传输。在我看来,WebRTC现在太不稳定,无法直接使用。以下适用于Chrome / FF / Opera:
<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>