Domanda

Sto cercando di passare un messaggio esadecimale da un server C a un client Java. La comunicazione funziona.Ma il valore esadecimale che ottengo sul client Java sembra essere aggiunto con "ff".Perché sta succedendo?

Sul lato C, quando stampo i byte che voglio inviare (in Hex), sembrano a posto.

Vedere il codice di seguito:

Server C:

                    int datalen = 220;

                    /* create  outgoing message */
                    idx = 0;
                    en_outmsg[idx++] = FEB & 0xFF;
                    en_outmsg[idx++] = ENT & 0xFF;
                    en_outmsg[idx++] = CBA & 0xFF;
                    en_outmsg[idx++] = GRP & 0xFF;
                    en_outmsg[idx++] = OUTGOING & 0xFF;
                    en_outmsg[idx++] = (datalen & 0xFF00) >> 8;
                    en_outmsg[idx++] = datalen & 0xFF;

                    for(i= 0; i<39; i++){
                    printf("en_outmsg[%d] to send = %x\n",i, en_outmsg[i]);
                    }
                    en_outmsg[i+1] = '\n';


                    if (send(connected, en_outmsg, 40, 0) > 0)
                    {
                        printf("sending over\n");

                    }

Client Java:

    while( (bytes =dis.read(buffer, 0, 40)) != -1){
        for(int index=38; index >= 0; index--)  {           

                System.out.println("index ="+index);
                System.out.println("buffer ="+Integer.toHexString(buffer[index]));
        }
        System.out.println("bytes="+bytes); 
        len = 0;
        len |= buffer[5];
        len = len << 8;
        len |=  buffer[6];
        System.out.println("value of len= "+len);
    }

Uscita: valore di len= -36 buffer [5]= 0 buffer [6]= 0xfffffffdc

AGGIORNATO

Ecco il mio output di WireShark (questo è ciò che il server C invia al client Java):

Notare che alla riga 5 "00 dc" corrisponde a datalen= 220 che dovrebbe essere memorizzato come tale in len sul client Java.Quindi c'è chiaramente qualche errore sul client Java.Come tutti voi avete detto, posso usare Integer.toHexString (((int) buffer [index]) & 0xFF) per la stampa.Ma ho bisogno di memorizzare l'array di byte con i valori esadecimali corretti.Per favore aiutatemi

0000  00 00 03 04 00 06 00 00  00 00 00 00 00 00 08 00   ........ ........
0010  45 00 00 5c b4 75 40 00  40 06 a0 ac c0 a8 b2 14   E..\.u@. @.......
0020  c0 a8 b2 14 09 60 b7 bb  fe bd 3a 2d fe 36 cc 8c   .....`.. ..:-.6..
0030  80 18 02 20 e5 c8 00 00  01 01 08 0a 00 04 8e 5f   ... .... ......._
0040  00 04 8e 5f 0a 01 01 16  01 00 dc 00 01 02 03 04   ..._.... ........
0050  05 06 07 08 09 0a 0b 0c  0d 0e 0f 2b 7e 15 16 28   ........ ...+~..(
0060  ae d2 a6 ab f7 15 88 09  cf 4f 3c d0               ........ .O<.    
È stato utile?

Soluzione

Il primo passo in queste situazioni dovrebbe essere vedere cosa viene inviato "via cavo". Se puoi, considera l'utilizzo di wirehark o tcpdump per vedere cosa viene trasmesso. In questo modo, puoi capire cosa non funziona come previsto. Entrambi possono monitorare i socket associati a IP locali così come i socket di loopback.

Ma a quanto pare, sono d'accordo sul fatto che sia in corso uno scontro firmato / non firmato.

Se hai questo output, sarebbe utile per determinare "chi" è in colpa.

<⇨Update:

Come è stato detto, dovrai mascherare e utilizzare solo gli 8 bit più bassi e questo può essere fatto:

b = b & 0xFF

Puoi introdurlo nel tuo codice in due modi, uno è attraverso una semplice funzione statica che chiameresti per ogni byte, ad esempio

public static int mask(int rawbyte)
{
    return (rawbyte & 0xFF);
}

L'altra è una funzione wrapper per DataInputStream.read () che legge i byte in un buffer e poi li maschera tutti. Potrebbe avere un aspetto simile a:

public static int socket_read(DataInputStream dis, int arr[], int off, int len)
{
    b = new byte[len];
    int rv = dis.read(b, off, len);
    for(int i=0; i < len; i++)
    {
        arr[i] = ((int)b[i]) & 0xFF;
    }
    return rv;
}

Se scegli il primo modo, dovresti chiamare mask () su qualsiasi valore di buffer [] che usi. Quindi

len |= buffer[5];

sarebbe

len |= mask(buffer[5]);

Se scegli il secondo modo, cambierai il buffer da un array di tipo byte a int:

buffer = new int[...]

e potrebbe aggiornare il tuo ciclo while a qualcosa del tipo:

while( (bytes = socket_read(dis, buffer, 0, 40)) != -1)

Ma detto questo ...

Un'opzione migliore di entrambe è quella di utilizzare metodo readUnsignedByte di DataInputStream .

Avresti bisogno di estrarre dallo stream 40 byte alla volta, ma sarebbe molto più chiaro cosa stavi facendo piuttosto che giocherellare un po '. Questo sarebbe l'approccio preferito a mio parere.

Altri suggerimenti

I byte in java sono firmati.Quindi ogni valore che ha il bit più significativo impostato è un valore negativo.Quando viene convertito in un numero intero, cosa che accade quando chiami Integer.toHexString, il segno viene esteso.Quindi, se era 10000000b, diventerà 11111111111111111111111110000000b o 0xFFFFFF80 invece di 0x80.Perché questo è lo stesso valore negativo a 32 bit.In corso

Integer.toHexString(((int)buffer[index]) & 0xFF)

Dovrebbe risolverlo.

BTW, java non ha tipi senza segno.

But the hex value that I get on Java client seems to be appended with "FF"

Integer.toHexString(buffer[index] & 0xFF ) risolverà il tuo problema.

Sembra una propagazione dei bit di segno.len e altre variabili JAVA sembrano firmate quando non dovrebbero.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top