5

Attualmente sto scrivendo un programma Java che comunica con un'estensione di Chrome. Devo implementare il protocollo di messaggistica nativa di Chrome per comunicare. I documenti di Google Chrome dicono:Java nativo di messaggistica con estensione chrome - Impossibile scrivere correttamente la lunghezza

... ogni messaggio viene serializzato usando JSON, codificato UTF-8 ed è preceduto da una lunghezza di messaggio di 32 bit in ordine di byte nativo. (Source)

ho cercato di attuare questo in Java, ma non ho problemi quando i miei messaggi hanno una certa lunghezza, anche se la mia applicazione dovrebbe essere corretto. Ecco il mio attuale implementazione, sulla base di precedenti SO-risponde & domande (here per esempio):

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

Sembra che il problema risiede nel modo in cui Java implementa caratteri. Mi aspetterei caratteri normali, come in C. In pratica, sembra che Java a volte trasformi questi caratteri in caratteri unicode (o almeno, questo è il mio sospetto fino ad ora). Questo si riflette nella seguente output (convogliato xxD visualizzare i byte reali) dal java-programma di lunghezza 2269:

0000000: c39d 0800 00        ..... 

L'output previsto però (con pitone):

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

Nei sta succedendo esattamente qui? Perché Java converte il mio "0xDD" in "0xC39D" e come posso ottenere la mia funzione getBytes per rappresentare l'input previsto per Chrome Native Messaging? L'utilizzo di un'altra lingua non è un'opzione.

risposta

4

I caratteri in Java vengono automaticamente trasformati in unicode. Il tipo corretto per questo caso d'uso è byte, che non si trasforma e mantiene automaticamente il valore corretto. Una corretta implementazione del protocollo Chrome nativo Messaging è dunque la seguente:

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

Oltre a questo metodo, la cura deve essere utilizzato non utilizzare una stringa qualsiasi punto tra il calcolo della lunghezza-byte e l'uscita. Uscita per System.out può essere fatto come segue:

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

ho usato si risponde ma non ha work.I ottenere questo errore nel lato interno: applicazione nativa ha tentato di inviare un messaggio di 977472013 byte, che supera il limite di 1048576 byte. – Leon

+0

Provare a eseguire l'applicazione manualmente e collegarla tramite xxd. Questo dovrebbe portarti in pista cercando di scoprire cosa non va. Probabilmente stai emettendo una nuova riga (\ r \ n) prima dell'effettivo output. 'struct.pack ('I', 977472013)' -> ''\ r \ nC:''. Un messaggio corretto invia prima la lunghezza e quindi il contenuto effettivo. – Snicksie

Problemi correlati