Pregunta

Estoy intentando pasar un mensaje hexadecimal desde un servidor C a un cliente Java. La comunicación funciona.Pero el valor hexadecimal que obtengo en el cliente Java parece estar agregado con "ff".¿Por qué sucede esto?

En el lado C, cuando imprimo los bytes que quiero enviar (en hexadecimal), parecen estar bien.

Consulte el código a continuación:

Servidor 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");

                    }

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

Salida: valor de len= -36 búfer [5]= 0 búfer [6]= 0xfffffffdc

ACTUALIZADO

Aquí está mi salida de wirehark (esto es lo que el servidor C envía al cliente Java):

Tenga en cuenta que en la fila 5 "00 dc" corresponde a datalen= 220 que debe almacenarse como tal en len en el cliente Java.Entonces, claramente hay algún error en el Cliente Java.Como todos han mencionado, puedo usar Integer.toHexString (((int) buffer [index]) & 0xFF) para imprimir.Pero necesito almacenar la matriz de bytes con los valores hexadecimales correctos.Ayuda por favor

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<.    
¿Fue útil?

Solución

Su primer paso en esta situación debería ser ver qué se envía "por cable". Si puede, considere usar wirehark o tcpdump para ver qué se está transmitiendo. De esa manera, puede averiguar qué no funciona como se esperaba. Ambos pueden monitorear sockets vinculados a IP locales así como sockets de loopback.

Pero por lo que parece, estoy de acuerdo en que se está produciendo un conflicto firmado / no firmado.

Si tiene este resultado, sería útil para determinar "quién" tiene la culpa.

<”Actualización:

Como se ha mencionado, querrá enmascarar y usar solo los 8 bits más bajos y esto se puede hacer mediante:

b = b & 0xFF

Puede introducir esto en su código de dos formas, una es a través de una función estática simple que llamaría para cada byte, p. ej.

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

La otra es una función contenedora para DataInputStream.read () que leería los bytes en un búfer y luego los enmascararía a todos. Podría verse algo como:

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

Si elige la primera forma, querrá llamar a mask () en cualquier valor de búfer [] que use. Entonces

len |= buffer[5];

sería

len |= mask(buffer[5]);

Si elige la segunda forma, entonces cambiaría el búfer de una matriz de tipo byte a int:

buffer = new int[...]

y podría actualizar su ciclo while a algo como:

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

Pero dicho eso ...

Una opción mejor que cualquiera de estas es hacer uso de Método readUnsignedByte de DataInputStream .

Debería extraer 40 bytes de la transmisión a la vez, pero sería mucho más claro lo que estaba haciendo en lugar de jugar un poco. Este sería el enfoque preferido en mi opinión.

Otros consejos

Los bytes en java están firmados.Entonces, cada valor que tiene el bit más significativo establecido es un valor negativo.Cuando se convierte a un número entero, lo que sucede cuando llama a Integer.toHexString, el signo se extiende.Entonces, si era 10000000b, se convertirá en 11111111111111111111111110000000b o 0xFFFFFF80 en lugar de 0x80.Porque ese es el mismo valor negativo en 32 bits.Haciendo

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

Debería solucionarlo.

Por cierto, java no tiene tipos sin firmar.

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

Integer.toHexString(buffer[index] & 0xFF ) solucionará su problema.

Suena como propagación de bits de signo.len y otras variables JAVA parecen firmadas cuando no deberían.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top