Receiving WebSocket ArrayBuffer data in the browser - receiving string instead

arraybuffer, javascript, node.js, websocket

Solution

send binary data use `sendBytes()` method.

Problem

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.

Original source

Related problems