2014-09-01 14 views
5

Tôi hiện đang viết một chương trình Java giao tiếp với tiện ích mở rộng của Chrome. Tôi cần triển khai giao thức gửi thư gốc của Chrome để giao tiếp. Tài liệu Google Chrome cho biết:Nhắn tin gốc Java với tiện ích chrome - không thể viết chính xác độ dài

... mỗi thư được tuần tự hóa bằng JSON, UTF-8 được mã hóa và được đặt trước với độ dài 32 bit theo thứ tự byte gốc. (Source)

Tôi đã cố gắng thực hiện điều này trong Java, nhưng tôi gặp sự cố khi thư của tôi có độ dài nhất định, mặc dù việc triển khai của tôi phải chính xác. Dưới đây là thực hiện hiện tại của tôi, dựa trên trước SO-trả lời câu hỏi & (here ví dụ):

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

Có vẻ như vấn đề nằm ở cách java thực hiện ký tự. Tôi mong đợi các ký tự bình thường, như trong C. Trong thực tế, có vẻ như Java đôi khi biến những ký tự này thành ký tự unicode (hoặc ít nhất, đó là nghi ngờ của tôi cho đến nay). Này được phản ánh trong các kết quả như sau (đường ống để xxd để hiển thị các byte thực tế) từ java-chương trình cho chiều dài 2269:

0000000: c39d 0800 00        ..... 

Sản lượng dự kiến ​​tuy nhiên (với python):

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

gì chính xác đang xảy ra ở đây? Tại sao Java chuyển đổi "0xDD" thành "0xC39D" của tôi và làm cách nào tôi có thể nhận được hàm getBytes của mình để biểu thị đầu vào dự kiến ​​cho Nhắn tin gốc của Chrome? Sử dụng ngôn ngữ khác không phải là một lựa chọn.

Trả lời

4

Ký tự trong Java được tự động chuyển thành unicode. Loại chính xác cho trường hợp sử dụng này là byte, không tự động chuyển đổi và giữ giá trị chính xác. Một thực hiện đúng các giao thức Chrome Native Messaging là như vậy, như sau:

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

Bên cạnh đó phương pháp này, việc chăm sóc cần được sử dụng không sử dụng một chuỗi bất cứ nơi nào giữa việc tính độ dài-byte và đầu ra. Output để System.out thể được thực hiện như sau:

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

i sử dụng bạn trả lời nhưng nó không work.i nhận được lỗi này ở bên gia hạn: Ứng dụng Native cố gắng để gửi một thông điệp của 977.472.013 byte, mà vượt quá giới hạn 1048576 byte. – Leon

+0

Cố gắng chạy ứng dụng của bạn theo cách thủ công và chuyển nó qua xxd. Điều đó sẽ giúp bạn đi đúng hướng với cố gắng tìm hiểu những gì đang xảy ra. Có khả năng bạn đang xuất một dòng mới (\ r \ n) trước khi đầu ra thực tế. 'struct.pack ('I', 977472013)' -> ''\ r \ nC:''. Một thông điệp chính xác đầu tiên gửi chiều dài, và sau đó là nội dung thực tế. – Snicksie

Các vấn đề liên quan