【发布时间】:2014-02-07 19:06:09
【问题描述】:
我正在尝试使用 WebRTC DataChannels 创建一个简单的网页,该网页在浏览器之间发送 pings/pongs。
当 Chrome 启动连接,然后 Chrome 连接时,它工作。
当 Firefox 启动连接,然后 Firefox 连接时,它工作。
当 Chrome 启动连接,然后 Firefox 连接时,它工作。
但是当 Firefox 启动连接然后 Chrome 连接时,它不起作用。 Chrome 从不接收 Firefox 发送的数据。
我在 Archlinux 上使用 Firefox 26 和 Chromium 32。
这是我的 JavaScript 代码:
<!DOCTYPE html>
<html>
<head>
<title>WebRTC test</title>
<meta charset="utf-8">
</head>
<body>
<button id="create" disabled>Create data channel</button>
<script type="text/javascript">
// DOM
var create = document.getElementById('create');
// Compatibility
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
window.RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription;
window.RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.webkitRTCIceCandidate;
// Create a WebRTC object
var rtc = new RTCPeerConnection(null);
// Create a data channel
var sendChannel = rtc.createDataChannel('pingtest', {reliable: false});
var myMsg = 'ping';
function setRecvChannel(recvChannel) {
recvChannel.onmessage = function(event) {
if(event.data.indexOf('\x03\x00\x00\x00\x00\x00\x00\x00\x00') === 0) {
console.log('-> ' + window.btoa(event.data));
return; // Received channel's name, ignore
}
console.log('-> ' + event.data);
window.setTimeout(function() {
console.log('<- ' + myMsg);
sendChannel.send(myMsg);
}, 500);
};
}
// Chrome and Firefox
sendChannel.onopen = function(event) {
setRecvChannel(sendChannel);
if(myMsg === 'ping') {
console.log('<- ' + myMsg);
sendChannel.send(myMsg);
}
};
// Firefox
rtc.ondatachannel = function(event) {
setRecvChannel(event.channel);
};
// ICE
rtc.onicecandidate = function(event) {
if(event.candidate) {
console.log('<- ' + JSON.stringify(event.candidate));
ws.send(JSON.stringify(event.candidate));
}
};
// Signaling channel
var ws = new WebSocket('ws://127.0.0.1:49300/');
ws.onopen = function() {
create.disabled = false;
};
ws.onmessage = function(event) {
console.log('-> ' + event.data);
var data = JSON.parse(event.data);
if(data.sdp) {
rtc.setRemoteDescription(new RTCSessionDescription(data));
if(data.type === 'offer') {
myMsg = 'pong';
rtc.createAnswer(function(anwser) {
rtc.setLocalDescription(anwser, function () {
console.log('<- ' + JSON.stringify(anwser));
ws.send(JSON.stringify(anwser));
});
}, console.error);
}
}
else {
rtc.addIceCandidate(new RTCIceCandidate(data));
}
};
ws.onclose = function() {
create.disabled = true;
};
// Create an offer
create.onclick = function() {
rtc.createOffer(function(offer) {
rtc.setLocalDescription(offer, function () {
offer.sdp = offer.sdp;
console.log(offer.sdp);
console.log('<- ' + JSON.stringify(offer));
ws.send(JSON.stringify(offer));
});
}, console.error);
};
</script>
</body>
</html>
这是我创建的基于 WebSocket 的信令服务器,仅用于测试目的,它只是侦听端口 49300 并将从客户端接收到的数据广播到其他客户端:
#!/usr/bin/python
#-*- encoding: Utf-8 -*-
from socket import socket, AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
from string import printable
from threading import Thread
from base64 import b64encode
from struct import unpack
from hashlib import sha1
PORT = 49300
activeSocks = []
def SignalingChannel(ip, port, sock):
print 'Connection from %s:%s' % (ip, port)
# Handling the HTTP request
try:
headers = sock.recv(8184)
assert headers.upper().startswith('GET')
assert headers.endswith('\r\n\r\n')
data = headers.strip().replace('\r', '').split('\n')[1:]
headers = {}
for header in data:
name, value = header.split(':', 1)
headers[name.strip().lower()] = value.strip()
assert headers['host']
assert 'upgrade' in headers['connection'].lower()
assert 'websocket' in headers['upgrade'].lower()
assert headers['sec-websocket-version'] == '13'
assert len(headers['sec-websocket-key']) == 24
guid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
accept = b64encode(sha1(headers['sec-websocket-key'] + guid).digest())
sock.send('HTTP/1.1 101 Switching Protocols\r\n' +
'Connection: Upgrade\r\n' +
'Upgrade: websocket\r\n' +
'Sec-WebSocket-Accept: %s\r\n' % accept +
'\r\n')
except:
try:
msg = 'This is a RFC 6455 WebSocket server.\n'
sock.send('HTTP/1.1 400 Bad Request\r\n' +
'Connection: Close\r\n' +
'Content-Length: %d\r\n' % len(msg) +
'Content-Type: text/plain; charset=us-ascii\r\n' +
'Sec-WebSocket-Version: 13\r\n' +
'\r\n' +
msg)
except:
pass
sock.close()
print 'Disconnection from %s:%s' % (ip, port)
return
activeSocks.append(sock)
try:
data = sock.recv(2)
while len(data) == 2:
frame = data[0] + chr(ord(data[1]) & 0b01111111)
opcode = ord(data[0]) & 0b00001111
mask = ord(data[1]) & 0b10000000
paylen = ord(data[1]) & 0b01111111
if paylen == 126:
data = sock.recv(2)
frame += data
paylen = unpack('>H', data)[0]
elif paylen == 127:
data = sock.recv(8)
frame += data
paylen = unpack('>Q', data)[0]
if mask:
mask = sock.recv(4)
data = ''
received = True
while received and len(data) < paylen:
received = sock.recv(paylen - len(data))
data += received
if mask:
unmasked = ''
for i in xrange(len(data)):
unmasked += chr(ord(data[i]) ^ ord(mask[i % 4]))
else:
unmasked = data
frame += unmasked
if opcode != 8:
print '-- From port %d --' % port
if all(ord(c) < 127 and c in printable for c in unmasked):
print unmasked
else:
print repr(unmasked)
for destSock in activeSocks:
if destSock != sock:
destSock.send(frame)
else:
break
data = sock.recv(2)
except:
pass
activeSocks.remove(sock)
sock.close()
print 'Disconnection from %s:%s' % (ip, port)
listenSock = socket(AF_INET, SOCK_STREAM)
listenSock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
listenSock.bind(('0.0.0.0', PORT))
listenSock.listen(20)
print 'Listening on port 49300...'
while True:
clientSock, (ip, port) = listenSock.accept()
Thread(target=SignalingChannel, args=(ip, port, clientSock)).start()
要运行代码,启动信号服务器,在两个浏览器选项卡中打开网页,单击“创建数据通道”按钮并查看 Web 控制台。
有什么想法吗?
【问题讨论】:
标签: javascript html google-chrome interop webrtc