Pergunta

Estou tentando passar uma mensagem hexadecimal de um servidor C para um cliente Java. A comunicação funciona.Mas o valor hexadecimal que obtenho no cliente Java parece estar anexado com "ff".Por que isso está acontecendo?

No lado C, quando imprimo os bytes que desejo enviar (em Hex), eles parecem ok.

Por favor, veja o código abaixo:

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

Saída: valor de len= -36 buffer [5]= 0 buffer [6]= 0xfffffffdc

ATUALIZADO

Aqui está minha saída do WireShark (isto é o que o servidor C envia para o cliente Java):

Observe que na linha 5 "00 dc" corresponde a datalen= 220 que deve ser armazenado como tal em len no cliente Java.Portanto, há claramente algum erro no cliente Java.Como todos mencionaram, posso usar Integer.toHexString (((int) buffer [index]) & 0xFF) para impressão.Mas preciso armazenar a matriz de bytes com os valores hexadecimais corretos.Por favor ajude

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

Solução

Sua primeira etapa nessa situação deve ser ver o que está sendo enviado "através da transferência". Se você puder, considere usar fioshark ou tcpdump para ver o que está sendo transmitido. Dessa forma, você pode descobrir o que não está funcionando conforme o esperado. Ambos podem monitorar soquetes vinculados a IPs locais, bem como soquetes de loopback.

Mas ao que parece, eu concordaria que há um conflito assinado / não assinado em andamento.

Se você tiver esta saída, seria útil para determinar "quem" é o culpado.

<"Atualizar:

Como foi mencionado, você desejará remover a máscara e usar apenas os 8 bits mais baixos e isso pode ser feito por:

b = b & 0xFF

Você pode introduzir isso em seu código de duas maneiras, uma é por meio de uma função estática simples que você chamaria para cada byte, por exemplo,

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

A outra é uma função de wrapper para DataInputStream.read () que lê os bytes em um buffer e, em seguida, mascara todos eles. Pode ser 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;
}

Se você escolher a primeira maneira, deverá chamar mask () em qualquer valor buffer [] que usar. Então,

len |= buffer[5];

seria

len |= mask(buffer[5]);

Se você escolher a segunda maneira, deverá alterar o buffer de uma matriz do tipo byte para int:

buffer = new int[...]

e poderia atualizar seu loop while para algo como:

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

Mas dito isso ...

Uma opção melhor do que qualquer uma dessas é usar Método readUnsignedByte de DataInputStream .

Você mesmo precisaria retirar 40 bytes do fluxo de cada vez, mas ficaria muito mais claro o que você estava fazendo ao invés de mexer um pouco. Essa seria a abordagem preferida na minha opinião.

Outras dicas

Os bytes em java são assinados.Portanto, cada valor que possui o conjunto de bits mais significativo é um valor negativo.Quando ele é convertido para um inteiro, o que acontece quando você chama Integer.toHexString, o sinal é estendido.Portanto, se fosse 10000000b, ele se tornaria 1111111111111111111111111110000000b ou 0xFFFFFF80 em vez de 0x80.Porque esse é o mesmo valor negativo em 32 bits.Fazendo

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

Deve consertar.

A propósito, java não tem tipos não assinados.

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

Integer.toHexString(buffer[index] & 0xFF ) resolverá o seu problema.

Parece propagação de bit de sinal.len e outras variáveis JAVA parecem assinadas, mas não deveriam.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top