如何将javascript数组转换为二进制数据并返回websocket?

时间:2016-09-27 13:17:48

标签: javascript websocket

我想发送这个示例数组

[{
    id: 1,
    name: "test",
    position: [1234,850], //random position on the map
    points: 100 //example points
}];

以我的websocket服务器作为二进制数据。在服务器端,我希望将二进制数据解码回数组,进行更改并将二进制数据发送回客户端。最后在客户端如何将二进制数据解码回数组?

示例屏幕截图我的意思是:

enter image description here

这是我的实际代码:

var connection = new WebSocket('wss://my_website.eu:1234');
connection.binaryType = "ArrayBuffer";
connection.onmessage = function (event) {

    // console.log(event);
    if (event.data instanceof window["ArrayBuffer"]) {
        var data3 = JSON.parse(String.fromCharCode.apply(null, new Uint16Array(event.data)));
        console.log(data3);
    } else {
        console.log(event.data); // Blob {size: 0, type: ""}
    }
};

$("body").mousemove(function( event ) {

    var data = {
        name: "lol",
        pos: [event.pageX, event.pageY]
    };

    //convert to binary frame
    var data2 = new Uint16Array(data);
    console.log(data2); // []

    //try to convert back to array
    var data3 = String.fromCharCode.apply(null, new Uint16Array(data2));
    console.log(data3); // empty

    connection.send(data2); // Binary Frame (Opcode 2, mask) | length: 0

});

服务器端代码:

connection.on('message', function(message) {
    for (var i = players.length - 1; i >= 0; i--) {
        players[i].connection.send(message.binaryData);
    }
});

最新编辑从这里阅读

我现在可以将消息作为二进制帧发送到websocket服务器。 I found functions将字符串转换为二进制类型并将其发送到ws服务器。

现在我有问题了。此功能(如下)不在服务器端工作。示例代码:

var data = {
    name: "value"
};

connection.send(JSON.stringify(data));

此代码运行良好。现在,当我尝试作为数组缓冲区发送时:

var data = {
    name: "value"
};

connection.send(StringToArrayBuffer(JSON.stringify(data)));

输出不是二进制帧,只是字符串“[object ArrayBuffer]”:

enter image description here

我也尝试过:

connection.send(JSON.stringify(data), {binary: true, mask: false});

但是这个发送消息是普通字符串,而不是二进制帧。

那么,如何将二进制帧从websocket服务器发送到客户端?当我发回收到的二进制消息:

connection.on('message', function(message) {
    for (var i = players.length - 1; i >= 0; i--) {
        playerConnection[i].send(message.binaryData);
    }
}

只有这样才有效。

2 个答案:

答案 0 :(得分:9)

首先,浏览器以不同于NodeJS的方式处理二进制数据。在浏览器中,二进制文件可以被视为ArrayBufferBuffer,但在NodeJS中,它被视为ArrayBuffer无法理解data。我不太深入,但你需要在浏览器和nodeJS之间区别对待BinaryType

在浏览器端使用WebSocket时,数据以字符串或二进制形式传输,如果使用二进制,则必须指定ArrayBuffer,在这种特殊情况下,我将使用{{1} }。

至于字符串到缓冲区,我建议使用标准的UTF-8,因为有两种编码UTF-16的方法。例如' \ u0024'在UTF-16中,UTF-16BE中存储为00 24,在UTF-16LE中,它存储为24 00.也就是说,如果要使用UTF-16,则应使用TextEncoder和TextDecoder。否则你可以简单地做到这一点



strToAB = str =>
  new Uint8Array(str.split('')
    .map(c => c.charCodeAt(0))).buffer;

ABToStr = ab => 
  new Uint8Array(ab).reduce((p, c) =>
  p + String.fromCharCode(c), '');

console.log(ABToStr(strToAB('hello world!')));




对于UTF-16,浏览器代码应类似于:

const ENCODING = 'utf-16le';
var ws = new WebSocket('ws://localhost');

ws.binaryType = 'arraybuffer';
ws.onmessage = event => {
  let str = new TextDecoder(ENCODING).decode(event.data),
    json = JSON.parse(str);
    console.log('received', json);
};
ws.onopen = () => {
  let json = { client: 'hi server' },
    str = JSON.stringify(json);
  console.log('sent',json);

  //JSON.toString() returns "[object Object]" which isn't what you want,
  //so ws.send(json) will send wrong data.
  ws.send(new TextEncoder(ENCODING).encode(str));
}

在服务器端,数据存储为Buffer,它或多或少地完成本地的所有操作。但是,您需要指定编码,除非它是UTF-8。

const ENCODING = 'utf-16le';
//You may use a different websocket implementation, but the core
//logic reminds as they all build on top of Buffer.
var WebSocketServer = require('websocket').server,
  http = require('http'),
  //This is only here so webSocketServer can be initialize.
  wss = new WebSocketServer({
    httpServer: http.createServer()
      .listen({ port: 80 })});

wss.on('request', request => {
  var connection = request.accept(null, request.origin);
  connection.on('message', msg => {
    if (msg.type === 'binary') {
      //In NodeJS (Buffer), you can use toString(encoding) to get
      //the string representation of the buffer.
      let str = msg.binaryData.toString(ENCODING);
      console.log(`message : ${str}`);

      //send data back to browser.
      let json = JSON.parse(str);
      json.server = 'Go away!';
      str = JSON.stringify(json);

      //In NodeJS (Buffer), you can create a new Buffer with a
      //string+encoding, and the default encoding is UTF-8.
      let buf = new Buffer(str, ENCODING);
      connection.sendBytes(buf);
    }
  });
});

答案 1 :(得分:2)

试一试:

发送数据示例:

var data = [{
    id: 1,
    name: "test",
    position: [1234, 850], //random position on the map
    points: 100 //example points
}];

var data2 = new Uint16Array(data);
socket.send(data2);

在你的事件onMessage websocket上尝试:

function onMessage(event) {

    if (event.data instanceof window["ArrayBuffer"]){
        var data3 = JSON.parse(String.fromCharCode.apply(null, new Uint16Array(event.data)));
    };

};