我使用Chrome中的WebRTC API设置了一个基本的视频聊天应用程序,以及我自己编写的WebSocket脚本,遵循W3C规范和其他问题。
有时候,当一台PC通过WebSocket连接向另一台PC发送ICE候选信息时,会在JSON字符串化的候选信息的末尾附加一堆乱码文本。 这个问题有时只会发生,而且通过createOffer和createAnswer方法发送的SDP信息不会发生这种情况。
请参阅以下链接,了解我所说的内容: http://s1290.beta.photobucket.com/user/HartleySan83/media/NGdata_zps0a7203e7.png.html?sort=3&o=0
因为JSON字符串化的候选信息总是以'}}'结尾,所以通过向WebSocket服务器脚本添加if条件,我能够绕过这个问题并使视频聊天应用程序正常工作。不幸的是,这是一个我想避免的黑客行为。另外,我想知道为什么会发生这种情况。
值得注意的是,当我在将候选信息发送到WebSocket服务器脚本之前向客户端的控制台发出警报或回显时,没有任何额外的乱码文本,所以我不确定它为什么存在在服务器端使用候选信息,有时只有。
以下是客户端代码的代码片段,其中候选信息被发送到服务器端脚本:
function startPeerConnection() {
navigator.webkitGetUserMedia({ audio: true, video: true }, function (stream) {
document.getElementById('vid1').src = webkitURL.createObjectURL(stream);
pc = new webkitRTCPeerConnection(null);
pc.onicecandidate = function (evt) {
if (evt.candidate) {
socket.send(JSON.stringify({ candidate: evt.candidate }));
}
};
pc.onaddstream = function (evt) {
document.getElementById('vid2').src = webkitURL.createObjectURL(evt.stream);
};
pc.addStream(stream);
}, function () {});
}
以下是取消屏蔽收到的WebSocket数据的服务器端代码:
$len = ord($buffer[1]) & 127;
if ($len === 126) {
$masks_start = 4;
} else if ($len === 127) {
$masks_start = 10;
} else {
$masks_start = 2;
}
$masks = substr($buffer, $masks_start, 4);
$data = substr($buffer, $masks_start + 4);
$len = strlen($data);
$text = '';
for ($i = 0; $i < $len; $i++) {
$text .= $data[$i] ^ $masks[$i % 4];
}
if (($end = strpos($text, '}}')) !== false) {
// This if condition eliminates the garbled text.
// Without it, a "Could not decode a text frame as UTF-8"
// error is output to the Chrome console.
$text = substr($text, 0, $end + 2);
$len = strlen($text);
}
if ($len <= 125) {
$header = pack('C*', 129, $len);
} else if (($len > 125) && ($len < 65536)) {
$header = pack('C*', 129, 126, ($len >> 8) & 255, $len & 255);
} else if ($len >= 65536) {
$header = pack('C*', 129, 127, ($len >> 56) & 255, ($len >> 48) & 255, ($len >> 40) & 255, ($len >> 32) & 255, ($len >> 24) & 255, ($len >> 16) & 255, ($len >> 8) & 255, $len & 255);
}
$server_response = $header . $text;
foreach ($users as $user) {
if ($user !== $users[$user_idx]) {
@socket_write($user['socket'], $server_response, strlen($server_response));
}
}
我在互联网上搜索了同样问题的其他任何人的高低,但是在规范中找不到任何人或任何事情,所以我想我的代码存在问题。
任何人都可以提供有关问题根源的任何指导,我们将不胜感激。 谢谢。
答案 0 :(得分:3)
好吧,我终于找到了问题。我的服务器端WebSocket代码确实是错误的。问题是我错误估计了长度。遗憾的是,我依赖于我在PHP中找到的关于WebSockets的一些页面,结果发现,该页面的代码中出现了一些错误,我慢慢开始越来越多地意识到这一点。无论如何,这是计算从客户端发送到服务器的消息长度的正确方法:
$len = ord($buffer[1]) & 127; // This is the default payload length.
if ($len === 126) { // If 126, then need to use the payload length at the 3rd and 4th bytes.
$masks_start = 4;
$len = (ord($buffer[2]) << 8) + ord($buffer[3]);
} else if ($len === 127) { // If 127, then need to use the next 8 bytes to calculate the length.
$masks_start = 10;
$len = (ord($buffer[2]) << 56) + (ord($buffer[3]) << 48) + (ord($buffer[4]) << 40) + (ord($buffer[5]) << 32) + (ord($buffer[6]) << 24) + (ord($buffer[7]) << 16) + (ord($buffer[8]) << 8) + ord($buffer[9]);
} else { // Otherwise, the default payload length is correct.
$masks_start = 2;
}
这样做之后,一切都很顺利。好吧,我还没弄清楚如何正确关闭WebSocket连接,但除此之外,WebRTC视频效果很好。
答案 1 :(得分:0)
在之前将client1 添加的乱码二进制数据是否会将其发送到Websocket服务器?或者你只是在websocket服务器处理后才在client2上看到它?我问,因为我遇到了similar problem,我的信令服务器(在这种情况下是SignalR)有一个错误,它破坏了我在PeerConnections之间发送的SDP。