带有 chrome 扩展的 Java native 消息传递 - 无法正确写入长度

标签 java google-chrome-extension chrome-native-messaging

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

... each message is serialized using JSON, UTF-8 encoded and is preceded with 32-bit message length in native byte order. (Source)

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

// 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]<< 0) & 0x000000ff;
}

// transform the length into the 32-bit message length. 
// This part works for small numbers, but does not work for length 2269 for example.
public static String getBytes(int length) {
    return String.format("%c%c%c%c", 
            (char) ( length      & 0xFF),
            (char) ((length>>8)  & 0xFF),
            (char) ((length>>16) & 0xFF),
            (char) ((length>>24) & 0xFF));
}

问题似乎出在 java 实现字符的方式上。我期望像 C 中那样的普通字符。实际上,Java 有时似乎会将这些字符转换为 unicode-chars(或者至少,这是我目前的怀疑)。这反射(reflect)在长度为 2269 的 java 程序的以下输出(通过管道传输到 xxd 以显示实际字节数)中:

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 中的字符会自动转换为 unicode。此用例的正确类型是 byte,它不会自动转换并保持正确的值。因此,Chrome native 消息传递协议(protocol)的正确实现如下:

    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;
    }

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

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

关于带有 chrome 扩展的 Java native 消息传递 - 无法正确写入长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25611271/

相关文章:

java - 如何将 SPDY 与 HttpClient 4 一起使用?

javascript - Chrome 扩展程序 : show page action if referrer url is google

javascript - Chrome 扩展 xmlHttpRequest 不起作用

javascript - Chrome 扩展程序和移动设备之间通过本地网络进行安全通信

google-chrome-extension - 将 Google Chrome 扩展程序限制为选择平台

java - 用定制的任务调度程序替换 Java 中的任务调度程序

java - 通过java正则表达式拆分

javascript - 为什么我收到 Chrome Native Messaging "Specified native messaging host not found."?

javascript - Vue 和原生消息传递

Java:使用 RuntimeException 逃离访问者