Analisi di un messaggio di lunghezza variabile
-
06-07-2019 - |
Domanda
Sto implementando il protocollo BitTorent usando Java tramite questa spec . Nella sezione messaggi tutti i messaggi hanno una lunghezza fissa tranne 2; per uno di questi è l'unico messaggio variabile dopo l'handshake, quindi posso controllare gli altri e supporre che sia un messaggio parziale quando nessun altro messaggio si incontra. Ma per il seguente messaggio
bitfield: <len=0001+X><id=5><bitfield>
Il messaggio bitfield può essere inviato immediatamente dopo il completamento della sequenza di sincronizzazione e prima che vengano inviati altri messaggi. È facoltativo e non deve essere inviato se un cliente non ha pezzi.
Il messaggio bitfield è di lunghezza variabile, dove X è la lunghezza del bitfield. Il payload è un bitfield che rappresenta i pezzi che sono stati scaricati con successo. Il bit alto nel primo byte corrisponde all'indice pezzo 0. I bit eliminati indicavano un pezzo mancante e i bit impostati indicano un pezzo valido e disponibile. I bit di riserva alla fine sono impostati su zero.
Un campo bit di lunghezza errata è considerato un errore. I client dovrebbero interrompere la connessione se ricevono campi di bit che non hanno le dimensioni corrette o se il campo di bit ha uno dei bit di riserva impostati.
Non riesco a trovare un modo per analizzarlo se non conosco la lunghezza; come dovrei individuare l'id in un flusso di byte?
Modifica: nel payload del messaggio bitfield sono gli 0 o 1 per ogni pezzo nel file torrent, la lunghezza del messaggio cambierà a seconda della dimensione del contenuto del torrent. Quindi non credo di poter presumere che il numero di pezzi si adatti sempre a un numero di 5 byte.
Soluzione
Il campo id
sarà sempre il 5 ° byte di un messaggio, dopo i quattro byte per il campo len
. Puoi fare qualcosa del tipo:
DataInputStream stream;
// ...
int length = stream.readInt();
byte id = stream.readByte();
byte[] payload = new byte[length - 1];
stream.readFully(payload);
Questo dovrebbe funzionare per qualsiasi messaggio, in realtà, poiché tutti hanno la stessa intestazione <=> + <=>.
Modifica: " Quindi non credo di poter supporre che il numero di pezzi si adatterà sempre in un numero di 5 byte. "
Un campo di lunghezza di quattro byte può gestire fino a 2 ^ 32-1 byte nel payload e con 8 bit per byte che offrono spazio per 34.359.738.360 pezzi. Dovrebbe essere un sacco! : -)
Altri suggerimenti
Non riesco a trovare un modo per analizzarlo se non conosco la lunghezza;
A giudicare dalla descrizione, la lunghezza è indicata nei primi 4 byte del messaggio.
come devo individuare l'id in a flusso di byte?
Sembra che l'id sia il 5 ° byte in ciascun messaggio, subito dopo il campo della lunghezza. Quindi devi solo guardare i primi 5 byte dopo aver finito di analizzare il messaggio precedente.
In precedenza nella specifica a cui facevi riferimento, ho letto: ' Il prefisso di lunghezza è un valore big-endian a quattro byte. '. L'ho letto come: leggi i prossimi quattro byte, convertili in un int e quello dovrebbe essere la tua lunghezza. Se non hai familiarità con il processo di conversione da byte a int, ho usato qualcosa di simile a questo .
Non ho letto le specifiche in dettaglio, ma senza conoscere esplicitamente la lunghezza di un campo di lunghezza variabile o delimitatore di terminazione, non vedo nemmeno come è possibile elaborarlo. Il bitfield=<len=0001+X>
non indica forse che ti verrà comunicato della lunghezza (variabile) in anticipo ?