Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Receiving WebSocket ArrayBuffer data in the browser - receiving string instead

I have a node.js server application and a browser client. Sending ArrayBuffer data browser -> server works perfectly, but server -> browser results in a string "[object ArrayBuffer]" being received. This happens in the latest versions of both Chrome and Firefox.

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

Client:

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

What am I doing wrong?

Edit:

From the node.js websocket source:

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

So if you use an Uint8Array, it sends the data as a string, instead of using sendBytes, as sendBytes needs a Buffer object. As in the answer below, I need sendBytes. As I can't pass an ArrayBuffer to sendBytes, I did this on the server:

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

Now it works.

Conclusion:

While Chrome and Firefox websockets .send() a Uint8Array buffer as binary data, it seems node.js websockets send it as string data, and you need a Buffer buffer to send binary.

like image 928
svinja Avatar asked Feb 23 '13 11:02

svinja


People also ask

How do I receive WebSocket data?

First, you need to copy your web browser's header to here and use json. dumps to convert it into the string format. After that, create the connection to the server by using create_connection . Then, perform the handshake by sending the message, and you will be able to see the data on your side.

How does WebSocket transmit data?

send() The WebSocket. send() method enqueues the specified data to be transmitted to the server over the WebSocket connection, increasing the value of bufferedAmount by the number of bytes needed to contain the data.

When using WebSocket send () How do you know when the data has been transmitted to the network?

The only way to know the client received the webSocket message for sure is to have the client send your own custom message back to the server to indicate you received it and for you to wait for that message on the server.

Can WebSockets send binary data?

Data Types and ExtensionsWebSockets support sending binary messages, too. To send binary data, one can use either Blob or ArrayBuffer object. Instead of calling the send method with string, you can simply pass an ArrayBuffer or a Blob .


1 Answers

send binary data use sendBytes() method.

like image 176
Tanaka Kenji Avatar answered Nov 11 '22 06:11

Tanaka Kenji