2013-02-23 22 views
6

Tôi có ứng dụng máy chủ node.js và trình duyệt trình duyệt. Gửi ArrayBuffer trình duyệt dữ liệu -> máy chủ hoạt động hoàn hảo, nhưng máy chủ -> kết quả trình duyệt trong chuỗi nhận được "[object ArrayBuffer]". Điều này xảy ra trong các phiên bản mới nhất của cả Chrome và Firefox.Nhận dữ liệu WebSocket ArrayBuffer trong trình duyệt - nhận chuỗi thay vì

Server:

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); 

Chủ đầu tư:

<!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> 

Tôi đang làm gì sai?

Edit:

Từ nguồn WebSocket Node.js:

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

Vì vậy, nếu bạn sử dụng một Uint8Array, nó sẽ gửi các dữ liệu như là một chuỗi, thay vì sử dụng sendBytes, như sendBytes nhu cầu một đối tượng Buffer. Như trong câu trả lời dưới đây, tôi cần sendBytes. Như tôi đã không thể vượt qua một ArrayBuffer-sendBytes, tôi đã làm điều này trên máy chủ:

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); 
    } 
} 

Bây giờ nó hoạt động.

Kết luận:

Trong khi Chrome và Firefox WebSockets .send() một bộ đệm Uint8Array như dữ liệu nhị phân, có vẻ như Node.js WebSockets gửi nó như string dữ liệu, và bạn cần một bộ đệm Buffer để gửi nhị phân.

+0

Cho rằng ArrayBuffer không hỗ trợ trong IE cho đến phiên bản 10 (mà hầu hết mọi người chưa có), tại sao không chỉ gửi dữ liệu văn bản cho khách hàng và tránh sự cố này? –

+0

Tôi muốn sử dụng số byte tối thiểu có thể vì tôi sẽ gửi dữ liệu rất nhanh cho nhiều khách hàng và tôi muốn ở dưới mức tổng cộng 10 kB/s trên máy chủ bao gồm cả chi phí. Có vẻ như ArrayBuffer là hoàn hảo cho điều đó, tôi không quan tâm liệu nó sẽ bao giờ làm việc trong IE một cách trung thực. Tôi chủ yếu cần nó để làm việc trong Chrome. – svinja

+0

Hãy xem xét điều này: http://stackoverflow.com/a/11426037/4323 –

Trả lời

4

gửi dữ liệu nhị phân sử dụng phương thức sendBytes().

+0

Tôi không chắc chắn lý do tại sao điều này làm cho một sự khác biệt, nhưng nó dường như làm việc (miễn là OP sẵn sàng sử dụng một Node Buffer thay vì một UInt8Array). –

5

Tôi đã chơi với WebSockets thời gian gần đây và ít nhất này dường như làm việc:

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); 
} 

Về cơ bản tôi chỉ cần tạo một mảng mới dựa trên event.data

Các vấn đề liên quan