如何在JavaScript中构建Websocket数据

时间:2014-08-07 17:53:54

标签: javascript websocket

我在https://stackoverflow.com/a/10402443/2755042找到了一篇文章,解释了如何编码/构建和解码websocket数据。我在编码部分遇到了麻烦。我能够成功地从客户端获取数据并将其记录到控制台,但当我转身并重新编码该消息并将其发送回客户端时,我收到错误:

net.js:614
throw new TypeError('invalid data');
      ^
TypeError: invalid data

以下是我的编码代码:

function encodeWebSocket(bytesRaw){
  var bytesFormatted = new Array();
  bytesFormatted[0] = 129;
  if (bytesRaw.length <= 125) {
    bytesFormatted[1] = bytesRaw.length;
  } else if (bytesRaw.length >= 126 && bytesRaw.length <= 65535) {
    bytesFormatted[1] = 126;
    bytesFormatted[2] = ( bytesRaw.length >> 8 ) & 255;
    bytesFormatted[3] = ( bytesRaw.length      ) & 255;
  } else {
    bytesFormatted[1] = 127;
    bytesFormatted[2] = ( bytesRaw.length >> 56 ) & 255;
    bytesFormatted[3] = ( bytesRaw.length >> 48 ) & 255;
    bytesFormatted[4] = ( bytesRaw.length >> 40 ) & 255;
    bytesFormatted[5] = ( bytesRaw.length >> 32 ) & 255;
    bytesFormatted[6] = ( bytesRaw.length >> 24 ) & 255;
    bytesFormatted[7] = ( bytesRaw.length >> 16 ) & 255;
    bytesFormatted[8] = ( bytesRaw.length >>  8 ) & 255;
    bytesFormatted[9] = ( bytesRaw.length       ) & 255;
  }
  for (var i = 0; i < bytesRaw.length; i++){
    bytesFormatted.push(bytesRaw.charCodeAt(i));
  }
  return bytesFormatted;
}

以下是使用encodeWebSocket函数的代码:

server.on('connection', function (socket) {
  socket.on('data', function (data) {
    // from client i send 'hello'
    var decodedMessage = (decodeWebSocket(data));
    console.log(decodedMessage); // hello
    console.log(typeof decodedMessage); // string
    var encodedMessage = encodeWebSocket(decodedMessage);
    socket.write(encodedMessage);
  });
});

基本上,我要做的就是创建一个接受消息的聊天服务器,然后转身并将其发送回所有其他连接的客户端。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

凯德答案中的代码是一个合理的开始。但是,以下代码中解决了一些问题。

首先,在处理unicode时,字符串长度和相应的缓冲区长度可能存在差异。例如:

> s = 'a'
'a'
> s.length
1
> b = new Buffer(s, 'utf-8')
<Buffer 61>
> b.length
1

但:

> s = 'å'
'å'
> s.length
1
> b = new Buffer(s, 'utf-8')
<Buffer c3 a5>
> b.length
2

因此,最好先将数据编码为Buffer,然后使用Buffer的长度作为有效负载长度。

此外,有效载荷长度可能> 1。 0xffff,其中有效负载长度需要8个字节,而不是2个。

下面代码中的另外两个细微差别是添加了可选的回调并将写入合并到一个调用中。虽然写入可能是缓冲的,但它们可能是两个系统调用。

function send(data, encoding, callback) {
  var socket = this;
  var header;
  var payload = new Buffer(data, encoding);
  var len = payload.length;
  if (len <= 125) {
    header = new Buffer(2);
    header[1] = len;
  } else if (len <= 0xffff) {
    header = new Buffer(4);
    header[1] = 126;
    header[2] = (len >> 8) & 0xff;
    header[3] = len & 0xff;
  } else { /* 0xffff < len <= 2^63 */
    header = new Buffer(10);
    header[1] = 127;
    header[2] = (len >> 56) & 0xff;
    header[3] = (len >> 48) & 0xff;
    header[4] = (len >> 40) & 0xff;
    header[5] = (len >> 32) & 0xff;
    header[6] = (len >> 24) & 0xff;
    header[7] = (len >> 16) & 0xff;
    header[8] = (len >> 8) & 0xff;
    header[9] = len & 0xff;
  }
  header[0] = 0x81;
  socket.write(Buffer.concat([header, payload], header.length + payload.length), 'binary', callback);
}

答案 1 :(得分:1)

经过大量搜索,这里是我设法编写数据以发送给客户端的代码:

function send(msg) {
  // http://stackoverflow.com/questions/8214910/node-js-websocket-send-custom-data
  var socket = this;
  var newFrame = new Buffer(msg.length > 125 ? 4 : 2);
  newFrame[0] = 0x81;
  if (msg.length > 125) {
    newFrame[1] = 126;
    var length = msg.length;
    newFrame[2] = length >> 8;
    newFrame[3] = length & 0xFF;
  }
  else {
    newFrame[1] = msg.length;
  }
  socket.write(newFrame, 'binary');
  socket.write(msg, 'utf8');
}