带有TCP / IP通信的javascript十六进制代码

时间:2016-05-09 17:29:40

标签: javascript node.js sockets tcp

我正在使用节点模块'net'来创建一个通过TCP套接字发送数据的客户端应用程序。如果服务器端应用程序以正确的十六进制代码开始和结束,则接受此消息,例如,数据包将以十六进制“0F”开头,并以十六进制“0F1C”结束。如何使用javascript创建这些十六进制代码?我发现这段代码将UTF-8字符串转换为十六进制代码,不确定这是否是我需要的,因为我没有太多的TCP / IP套接字连接经验。下面是一些javascript我用来将utf-8转换为十六进制代码。但我不确定这是我在找什么?有没有人有TCP / IP传输和/或javascript十六进制代码的经验?。

function toHex(str,hex){
  try{
    hex = unescape(encodeURIComponent(str))
    .split('').map(function(v){
      return v.charCodeAt(0).toString(16)
    }).join('')
  }
  catch(e){
    hex = str
    console.log('invalid text input: ' + str)
  }
  return hex
}

1 个答案:

答案 0 :(得分:2)

首先,您不需要将数据字符串转换为十六进制值,以便通过TCP发送它。 node.js中的每个字符串在通过网络发送时都会转换为字节。

通常情况下,您可以通过以下字符串发送:

var data = "ABC";
socket.write(data); // will send bytes 65 66 67, or in hex: 44 45 46

Node.JS还允许您将Buffer个对象传递给.write()等函数。 因此,实现您希望的最简单的方法是创建一个适当的缓冲区来保存您的数据。

var data = "ABC";
var prefix = 0x0F; // JavaScript allows hex numbers.
var suffix = 0x0FC1;
var dataSize = Buffer.byteLength(data);
// compute the required buffer length
var bufferSize = 1 + dataSize + 2;
var buffer = new Buffer(bufferSize);

// store first byte on index 0;
buffer.writeUInt8(prefix, 0);

// store string starting at index 1;
buffer.write(data, 1, dataSize);

// stores last two bytes, in big endian format for TCP/IP.
buffer.writeUInt16BE(suffix, bufferSize - 2);

socket.write(buffer);

<强>解释

prefix十六进制值0F需要1个字节的空间。 suffix十六进制值0FC1实际上需要两个字节(一个16位整数)。

当计算字符串(JavaScript字符串是UTF-16编码的!)所需的字节数时,str.length在大多数情况下都不准确,尤其是当你的字符串为非字符串时-ASCII中的字符。为此,获取字符串字节大小的正确方法是使用Buffer.byteLength()

node.js中的

Buffers具有静态分配,这意味着您无法在创建它们之后调整它们的大小。因此,在创建缓冲区 -in bytes - 之前,您需要计算它的大小。查看我们的数据,1(对于我们的前缀)+ Buffer.byteLength(data)(对于我们的数据)+ 2(对于我们的后缀)。

之后 -imagine缓冲区作为字节数组(8位值) - ,我们将填充缓冲区,如下所示:

  1. 在我们的缓冲区中使用prefix和偏移writeUInt8(byte, offset)写下第一个字节(0)。
  2. 使用.write(string[, offset[, length]][, encoding])编写数据字符串,从缓冲区中的偏移1开始,长度为dataSize
  3. 使用偏移.writeUInt16BE(value, offset)的{​​{1}}写下最后两个字节。我们正在使用bufferSize - 2 big-endian 编码中编写16位值,这是您对TCP / IP所需的。
  4. 我们使用正确的数据填充缓冲区后,我们可以使用writeUInt16BE在网络上发送;

    其他提示:

    如果你真的想将一个大字符串转换为字节,(例如以后打印为十六进制),那么socket.write(buffer)也很棒:

    Buffer

    由于字节都是0-255十进制值,因此您可以轻松地在控制台中将它们打印为十六进制值,如下所示:

    var buf = Buffer.from('a very large string');
    // now you have a byte represetantion of the string.