0

データの16ビットチェックサムを計算しています。サーバーに送信する必要があり、サーバーで再計算して、提供されたチェックサムと一致させる必要があります。取得しているチェックサム値はintですが、値を送信するためのバイトが2バイトしかないため、メソッドの呼び出し中にキャストintしています。これは、チェックサム値が32767未満になるまでは正常に機能し、その後は負の値になります。shortshortToBytes

Javaには符号なしプリミティブがないため、許可されている符号付きの最大値を超える値を送信することはできませんshort

どうすればこれを行うことができますか?intをshortに変換し、切り捨てやsigned&unsignedintを気にせずにネットワーク経由で送信します。

また、両側でJavaプログラムを実行しています。

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

4 に答える 4

1

まず、Javaintと型はすべて署名されており、署名されていませんshortbyte次に、Javaintshortなどにキャストすると、サイレントな切り捨てが発生します。

これが重要かどうかは、チェックサムアルゴリズムの性質によって異なります。単純な合計またはビット単位のアルゴリズムの場合、Java符号付き整数を使用して実装すると、アルゴリズムが問題ない可能性が高くなります。たとえば、これらの「負の」16ビットチェックサムは、符号なしの値を期待するものによって解釈された場合に正しい可能性があります。

一方、乗算と除算のセマンティクスでは、符号付きフレーバーと符号なしフレーバーを別々に処理する必要があります。(少なくとも、それは、x86命令セットを見るという非科学的なアプローチから推測するものです...これには、符号付きと符号なしの乗算と除算の別々の命令があります。)

編集あなたがCRC-16を計算していることを理解しています。これはシフトとXORによって計算できるため、計算中に符号付きの数値と符号なしの数値について心配する必要はありません。

つまり、心配することは何もありません。

于 2010-03-21T02:37:32.307 に答える
1

char符号なし16ビットタイプです。実際、これはJavaで唯一の符号なし型です。これをチェックサムの計算に使用してから、aを使用しByteBufferてバイトを取得するか、ビット単位および右シフトを使用してバイトを取得できます。

byteは署名されていることに注意してください。

于 2010-03-21T02:40:28.737 に答える
1

サーバーと同じビット値を取得しています。したがって、正しい数値を確認するには、をに置き換えByteBuffer.wrap(baValue).getShort()ますByteBuffer.wrap(baValue).getInt()。これにより、サーバーと同じ数値が得られるはずです。

于 2010-03-21T02:43:15.720 に答える
0

負の値を取得していると言うときは、16 ビット値を読み取って整数に変換するときを意味していると思います。これは、 が に拡張されたときに、符号拡張によって最上位ビット (1) が複製shortされるためintです。簡単な回避策は、再構築された整数を でビットごとに変換0xFFFFすることです。これにより、最下位の 16 ビットのみが非ゼロになることが保証されます。

于 2010-03-21T03:23:26.583 に答える