2010-03-21 5 views
0

Je calcule une somme de contrôle de 16 bits sur mes données que je dois envoyer au serveur où il doit recalculer et correspondre à la somme de contrôle fournie. La valeur de la somme de contrôle que j'obtiens est en int mais je n'ai que 2 octets pour l'envoi de la valeur. Donc, je lance int en short en appelant la méthode shortToBytes. Cela fonctionne bien jusqu'à ce que la valeur de checksum est inférieure à 32767 par la suite, je reçois des valeurs négatives. Il est vrai que java n'a pas de primitives non signées, donc je ne suis pas en mesure d'envoyer des valeurs supérieures à la valeur maximale de short signé autoriséjava convertir int en court

Comment puis-je faire cela, convertir int en court et envoyer sur le réseau sans se soucier de la troncature et signé & int.

Sur les deux côtés, j'ai un programme Java en cours d'exécution.

private byte[] shortToBytes(short sh) { 
     byte[] baValue = new byte[2]; 
     ByteBuffer buf = ByteBuffer.wrap(baValue); 
     return buf.putShort(sh).array(); 
    } 

    private short bytesToShort(byte[] buf, int offset) { 
     byte[] baValue = new byte[2]; 
     System.arraycopy(buf, offset, baValue, 0, 2); 
     return ByteBuffer.wrap(baValue).getShort(); 
    } 

Répondre

1

Vous obtenez toujours le même nombre de bits que le serveur. Donc, pour voir la bonne valeur numérique, remplacez le ByteBuffer.wrap(baValue).getShort() par un ByteBuffer.wrap(baValue).getInt(). Cela devrait vous donner la même valeur numérique que le serveur.

1

Tout d'abord, Java int, short et byte types sont tous signés non signé. Deuxièmement, lorsque vous lancez un Java int vers un short, vous obtiendrez une troncation silencieuse. Si cela compte, cela dépend de la nature de l'algorithme de somme de contrôle. Si c'est une simple somme, ou un algorithme bit à bit, il y a de fortes chances que l'algorithme soit parfait lorsqu'il est implémenté en utilisant des entiers signés Java. Par exemple, ces sommes de contrôle 16 bits "négatives" peuvent être correctes lorsqu'elles sont interprétées par quelque chose qui attend des valeurs non signées. D'autre part, la sémantique de la multiplication et de la division est telle que les arômes signés et non signés doivent être traités séparément. (Au moins, c'est ce que je déduis de l'approche non scientifique de regarder le jeu d'instructions x86 ... qui a des instructions distinctes pour signée par rapport à la multiplication et la division non signée.)

EDIT Je comprends que vous calculez CCR- 16 Comme cela peut être calculé en décalant et en XOR, il ne devrait pas y avoir de soucis concernant les nombres signés et non signés pendant le calcul.

En bref, vous n'avez rien à craindre.

+0

désolé j'ai oublié de préciser que la somme de contrôle est CRC16, donc en aucun cas il va avoir une valeur qui ne peut pas tenir dans 16 bits. – changed

1

char est un type 16 bits non signé. En fait, c'est le seul type non signé en Java. Vous pouvez l'utiliser pour calculer la somme de contrôle, puis utiliser un ByteBuffer pour obtenir les octets ou simplement utiliser le décalage bit à bit et à droite pour obtenir les octets. N'oubliez pas que byte s sont signés.

0

Lorsque vous dites que vous obtenez des valeurs négatives, je suppose que vous voulez dire quand vous lisez la valeur de 16 bits et la convertissez en nombre entier. La raison en est que l'extension de signe provoque la réplication du bit le plus significatif (qui est un 1) lorsque le short est élargi à int. La solution de contournement simple consiste à bitwise et l'entier reconstruit avec 0xFFFF, ce qui garantira que seuls les 16 bits les moins significatifs sont non-zéro.

+0

non, je veux dire quand un int est tronqué à court en Java. Dans mon cas, la valeur stockée dans int ne sera jamais grande pour ne pas correspondre à un réel 16 bits court. – changed