Question

J'essaie de passer un message hexadécimal d'un serveur C à un client Java. La communication fonctionne. Mais la valeur hexagonale que j'obtiens sur le client Java semble être ajoutée avec "FF". Pourquoi cela arrive-t-il?

Du côté C, lorsque j'imprime les octets que je veux envoyer (en hexadécimal), ils semblent corrects.

Veuillez consulter le code ci-dessous:

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

Sortie: valeur du tampon Len = -36 [5] = 0 tampon [6] = 0xfffffffdc

ACTUALISÉ

Voici ma sortie WireShark (c'est ce que C Server pousse au client Java):

Notez qu'à la ligne 5 "00 DC" correspond à Datalen = 220 qui doit être stocké en tant que tel dans Len sur le client Java. Il y a donc clairement une erreur sur le client Java. Comme vous l'avez tous mentionné, je peux utiliser Integer.tohexString (((int) buffer [index]) & 0xff) pour l'impression. Mais j'ai besoin de stocker le réseau d'octets avec les valeurs hexagonales correctes. Veuillez aider

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<.    
Était-ce utile?

La solution

Votre première étape dans cette situation devrait être de voir ce qui est envoyé "sur le fil". Si vous le pouvez, envisagez d'utiliser Wireshark ou tcpdump pour voir ce qui est transmis. De cette façon, vous pouvez comprendre ce qui ne fonctionne pas comme prévu. Les deux peuvent surveiller les sockets liés aux IPs locaux ainsi qu'aux prises de boucle.

Mais à première vue, je conviendrais qu'il y a un affrontement signé / non signé en cours.

Si vous avez cette sortie, il serait utile de déterminer "qui" est en faute.

Mise à jour:

Comme cela a été mentionné, vous voudrez masquer et utiliser uniquement les 8 bits les plus bas et cela peut être fait par:

b = b & 0xFF

Vous pouvez introduire cela dans votre code de deux manières, l'un consulte une fonction statique simple que vous appelleriez pour chaque octet, par exemple

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

L'autre est une fonction de wrapper pour datainputStream.read () qui lirait les octets dans un tampon, puis les masquerait tous. Cela pourrait ressembler à quelque chose:

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 vous choisissez la première façon, vous voudriez appeler Mask () sur n'importe quelle valeur tampon [] que vous utilisez. Alors

len |= buffer[5];

serait

len |= mask(buffer[5]);

Si vous choisissez la deuxième voie, vous changeriez de tampon à partir d'un tableau d'octet de type à Int:

buffer = new int[...]

Et pourrait mettre à jour votre boucle while sur quelque chose comme:

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

Mais cela étant dit ...

Une meilleure option que l'un ou l'autre est d'utiliser Méthode ReadUnSignedByte de DataNutStream.

Vous auriez besoin de retirer 40 octets du flux à la fois vous-même, mais il serait beaucoup plus clair ce que vous faisiez plutôt que de mordre. Ce serait l'approche préférée à mon avis.

Autres conseils

Les octets en Java sont signés. Ainsi, chaque valeur qui a l'ensemble de bits le plus significatif est une valeur négative. Lorsqu'il est converti en un entier qui se produit lorsque vous appelez Integer.Tohexstring Le signe est étendu. Donc, s'il était 10000000B, il deviendra 11111111111111111111110000000b ou 0xffffff80 au lieu de 0x80. Parce que c'est la même valeur négative en 32 bits. Action

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

Devrait le réparer.

BTW, Java n'a pas de types non signés.

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

Integer.toHexString(buffer[index] & 0xFF ) résoudra votre problème.

Cela ressemble à une propagation du bit de signe. Len et d'autres variables Java ressemblent à la signée alors qu'ils ne le devraient pas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top