【问题标题】:javascript hex codes with TCP/IP communication带有 TCP/IP 通信的 javascript 十六进制代码
【发布时间】:2016-05-11 15:25:06
【问题描述】:

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

【问题讨论】:

    标签: javascript node.js sockets tcp


    【解决方案1】:

    首先,您不需要将数据字符串转换为十六进制值,以便通过 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(我们的后缀)。

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

    1. 使用writeUInt8(byte, offset)在我们的缓冲区中写入第一个字节(prefix),偏移量为0
    2. 写入数据字符串,使用.write(string[, offset[, length]][, encoding]),从我们缓冲区中的偏移量1开始,长度为dataSize
    3. 写入最后两个字节,使用.writeUInt16BE(value, offset) 偏移bufferSize - 2。我们正在使用 writeUInt16BEbig-endian 编码写入 16 位值,这正是 TCP/IP 所需要的。

    一旦我们用正确的数据填充缓冲区,我们就可以使用socket.write(buffer)通过网络发送它;

    附加提示:

    如果您真的想将大字符串转换为字节,(例如,稍后打印为十六进制),那么Buffer 也很棒:

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

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

    for (i = 0; i < buf.length; i++) {
      const byte = buf[i];
      const hexChar = byte.toString(16); // convert the decimal `byte` to hex string;
      // do something with hexChar, e.g. console.log(hexChar);
    }
    

    【讨论】:

    • @MihaiPorta 这是很好的解释。这对我来说很清楚。但是,我仍然无法理解如何生成前缀和后缀。如果我 console.log(prefix) 它返回 15?你已经提到 javascript 允许十六进制数字,但是 var = 0x0F;当 console.logged 时结果为 15?
    • 使用 javascript 十六进制数字,您是否只是以 '0x' 开头的变量,而不是您喜欢的任何内容?当您控制台注销时,0 不显示,它真的存在吗?
    • 是的,JavaScript 语法允许您使用十六进制值,方法是在其前面加上 0x。所有十六进制值实际上都是数字(以 16 为底的小数)。 0x0F === 15。它们是相同的,所以console.log 将始终输出十进制(以 10 为底)表示。
    • 另外,0x0F0xF 相同,就像以 10 为底的 15015 相同。使用十六进制值时,通常包括前导 0 以更好地显示字节对齐,因为十六进制中的每两对都是一个字节长。例如。 0x0c010xc01 相同,表示两个字节 0c01
    • 非常感谢,这非常有帮助,这是对 TCP/IP 环境中 javascript 十六进制代码的一个很好的解释。
    猜你喜欢
    • 2016-04-06
    • 1970-01-01
    • 2015-08-10
    • 2017-04-27
    • 2023-01-29
    • 1970-01-01
    • 2016-11-28
    • 2019-01-01
    相关资源
    最近更新 更多