在浏览器中接收WebSocket ArrayBuffer数据 - 接收字符串

在浏览器中接收WebSocket ArrayBuffer数据 - 接收字符串

问题描述:

我有一个node.js服务器应用程序和一个浏览器客户端。发送ArrayBuffer数据浏览器 - >服务器完美工作,但服务器 - >浏览器导致接收字符串"[object ArrayBuffer]"。这发生在Chrome和Firefox的最新版本中。在浏览器中接收WebSocket ArrayBuffer数据 - 接收字符串

服务器:

var serverPort = 9867; 

// dependencies 
var webSocketServer = require('websocket').server; 
var http = require('http'); 
var players = {}; 
var nextPlayerId = 0; 

// create http server 
var server = http.createServer(function(request, response) { }); 
server.listen(serverPort, function() { 
    console.log((new Date()) + " Server is listening on port " + serverPort); 
}); 

// create websocket server 
var wServer = new webSocketServer({ httpServer: server }); 
// connection request callback 
wServer.on('request', function(request) { 
    var connection = request.accept(null, request.origin); 
    connection.binaryType = "arraybuffer"; 
    var player = {}; 
    player.connection = connection; 
    player.id = nextPlayerId; 
    nextPlayerId++; 
    players[player.id] = player; 
    console.log((new Date()) + ' connect: ' + player.id); 

    // message received callback 
    connection.on('message', function(message) { 
     if (message.type == 'binary' && 'binaryData' in message && message.binaryData instanceof Buffer) { 
      // this works! 
      console.log('received:'); 
      console.log(message); 

     } 
    }); 

    // connection closed callback 
    connection.on('close', function(connection) { 
     console.log((new Date()) + ' disconnect: ' + player.id); 
     delete players[player.id]; 
    }); 
}); 

function loop() { 
    var byteArray = new Uint8Array(2); 
    byteArray[0] = 1; 
    byteArray[0] = 2; 
    for (var index in players) { 
     var player = players[index]; 
     console.log('sending: '); 
     console.log(byteArray.buffer); 
     player.connection.send(byteArray.buffer); 
    } 
} 

timerId = setInterval(loop, 500); 

客户:

<!DOCTYPE html> 
<html> 
    <head> 
    </head> 
    <body> 
    <script type="text/javascript"> 

     window.WebSocket = window.WebSocket || window.MozWebSocket; 
     var connection = new WebSocket('ws://127.0.0.1:9867'); 
     connection.binaryType = "arraybuffer"; 

     // most important part - incoming messages 
     connection.onmessage = function (event) { 
     document.getElementById("log").innerHTML += typeof(event.data) + ' '; 
     document.getElementById("log").innerHTML += event.data + ' ';  
     if (event.data instanceof ArrayBuffer) { 
      // string received instead of a buffer 
     } 
     }; 

     window.onkeydown = function(e) { 
     var byteArray = new Uint8Array(2); 
     byteArray[0] = 1; 
     byteArray[1] = e.keyCode; 
     connection.send(byteArray.buffer); 
     }; 
    </script> 

    <div id='log'>Log: </div> 
    </body> 
</html> 

我在做什么错?

编辑:

从node.js中的WebSocket来源:

WebSocketConnection.prototype.send = function(data, cb) { 
    if (Buffer.isBuffer(data)) { 
     this.sendBytes(data, cb); 
    } 
    else if (typeof(data['toString']) === 'function') { 
     this.sendUTF(data, cb); 
    } 

因此,如果您使用的是Uint8Array,它发送的数据作为一个字符串,而不是使用sendBytes,作为sendBytes需求一个Buffer对象。正如在下面的答案中,我需要sendBytes。正如我不能传递一个ArrayBuffersendBytes,我这样做是在服务器上:

function loop() { 
    var buffer = new Buffer(2); 
    buffer[0] = 1; 
    buffer[1] = 2; 
    for (var index in players) { 
     var player = players[index]; 
     console.log('sending: '); 
     console.log(buffer); 
     player.connection.send(buffer); 
    } 
} 

现在,它的工作原理。

结论:

虽然Chrome和Firefox的WebSockets .send()一个Uint8Array缓冲区作为二进制数据,似乎node.js中的WebSockets将其作为string数据,你需要一个Buffer缓冲区来发送二进制。

+0

鉴于ArrayBuffer不支持新的阵列在IE直到第10版(大多数人还没有)之前,为什么不直接发送文本数据给客户端并避开这个问题呢? – 2013-02-23 11:45:23

+0

我想尽可能使用最小字节数,因为我将非常快速地向多个客户端发送数据,并且我希望在服务器上保持10kB/s以上的上游总计,包括开销。看起来像ArrayBuffer是完美的,我不在乎它是否会在IE中真正工作。我主要需要它在Chrome中工作。 – svinja 2013-02-23 11:53:06

+0

看看这个:http://*.com/a/11426037/4323 – 2013-02-23 11:55:55

发送二进制数据使用sendBytes()方法。

+0

我不完全确定这为什么会有所作为,但它似乎工作(只要OP愿意使用节点缓冲区而不是UInt8Array)。 – 2013-02-23 12:36:28

我最近一直在玩和使用WebSockets至少这似乎工作:

if(event.data instanceof ArrayBuffer) 
{ 
    var wordarray = new Uint16Array(event.data); 
    for (var i = 0; i < wordarray.length; i++) 
    { 
    console.log(wordarray[i]); 
    wordarray[i]=wordarray[i]+1; 
    } 
    console.log("End of binary message"); 
    console.log("sending changes"); 
    ws.send(wordarray.buffer); 
} 

基本上我只是创造基于event.data