带有chrome扩展名的Java本机消息传递 – 无法正确写入长度

我目前正在编写一个与Chrome扩展程序通信的Java程序。 我需要实现Chrome本机消息传递协议才能进行通信。 Google Chrome文档说:

…每条消息都使用JSON,UTF-8编码进行序列化,并以本机字节顺序开头的32位消息长度。 ( 来源 )

我试图用Java实现这个,但是当我的消息有一定的长度时我会遇到问题,即使我的实现应该是正确的。 这是我当前的实现,基于早期的SO-answers和问题(例如这里 ):

// read the message size from Chrome. This part works correctly. public static int getInt(char[] bytes) { return (bytes[3]<<24) & 0xff000000| (bytes[2]<<16) & 0x00ff0000| (bytes[1]<< 8) & 0x0000ff00| (bytes[0]<>8) & 0xFF), (char) ((length>>16) & 0xFF), (char) ((length>>24) & 0xFF)); } 

似乎问题在于java实现chars的方式。 我期待正常的字符,就像在C中一样。在实践中,似乎Java有时会将这些字符转换为unicode-chars(至少,到目前为止,这是我的怀疑)。 这反映在以下输出(通过管道传输到xxd以显示实际字节)中,来自java程序的长度为2269:

 0000000: c39d 0800 00 ..... 

但是预期的输出(使用python):

 import struct struct.pack('I', 2269) # outputs in interactive mode: '\xdd\x08\x00\x00' 

到底发生了什么? 为什么Java将我的“0xDD”转换为“0xC39D”?如何让我的getBytes函数代表Chrome Native Messaging的预期输入? 使用其他语言不是一种选择。

Java中的Chars会自动转换为unicode。 此用例的正确类型是byte ,它不会自动转换并保持正确的值。 因此,Chrome Native Messaging协议的正确实现如下:

  public static byte[] getBytes(int length) { byte[] bytes = new byte[4]; bytes[0] = (byte) ( length & 0xFF); bytes[1] = (byte) ((length>>8) & 0xFF); bytes[2] = (byte) ((length>>16) & 0xFF); bytes[3] = (byte) ((length>>24) & 0xFF); return bytes; } 

除了这种方法之外,还需要注意不要在计算长度字节和输出之间的任何地方使用String。 输出到System.out可以完成如下:

  try { System.out.write(getBytes(message.length())); } catch (IOException ex) { ex.printStackTrace(); }