1

現在のプロジェクトでは、いくつかの n ビット フィールドを含む解析済み構造をネットワーク経由で送信する必要があります。例えば:

  • プロトコル バージョン: 1 バイト
  • メッセージ ID: 1 バイト
  • creationTime: 6 バイト
  • traceId: 3 ビット
  • 信頼性: 7 ビット
  • 等...

したがって、解析と解析解除のためにこれを表す単純な POJO クラスを作成しましたが、これらのフィールドにどのタイプを使用するかについては疑問があります。ネットワーク経由で送信されるメッセージには、非常に具体的なサイズの制約があると言わざるを得ません。すべてのフィールドの合計を超えることはできません。

最初にすべてにバイトを使用することにしました。次に、メッセージを変換する Message.getBytes() メソッドを用意し、1 バイト未満のフィールドについては、ビット演算を使用して不要なビットを破棄します。

私は正しい方向に進んでいますか、それとももっと簡単な方法がありますか? ここで車輪を再発明しているように感じます。これは定型コードのような気がします...

ありがとう!

編集:他の誰かがここでつまずいた場合、私がこれをどのように解決したかを投稿します(これらを手伝ってくれた職場の仲間に感謝します)ので、読み続けてください:

幸いなことに、私のプロトコル ソケット サイズは固定バイト数 (49) に切り上げられ、バイト サイズ未満のフィールドは最後に 1 バイト合計されるため、解析前に両方のフィールドを 1 バイトに結合できます。 /解析中。

つまり、field1 と field2 という 2 つのフィールドがあるとします。最初は 7 ビットで、もう 1 つはほんの少しです。これらを組み合わせるには、次のトリックを実行します。

byte resultingByte = short2Byte((short) ((field1 % 128) * 2 + (field2 ? 1 : 0)));

field1 と field2 は両方とも short 型であることに注意してください。これがビットレベルで作業する最も便利な方法であることがわかりました。したがって、最初のフィールドを変更し、7 ビットのみを取得していることを確認し、移動する必要があるのは 1 ビットのみであるため、ビットを 2 だけ左に移動します。最後に、フィールド 2 ショート (1 または 0) を追加します。次に、8 下位ビットに必要な値を持つショートを作成します。

short2Byte、Long などから変換するコモディティ メソッドを作成しました。

private byte [] to2Bytes(int in) {
    ByteBuffer ret = ByteBuffer.allocate(2);
    int val = in % 65536;

    short s1 = (short) (val / 256);
    short s0 = (short) (val % 256);

    ret.put(short2Byte(s1));
    ret.put(short2Byte(s0));

    return ret.array();
}

private byte [] to4Bytes(long in) {
    ByteBuffer ret = ByteBuffer.allocate(4);
    long div = 4294967296L;
    long val = in % div;
    int rem = 0;

    short s3 = (short) (val / 16777216L);
    rem = (int) (val % 16777216L);
    short s2 = (short) (rem / 65536);
    rem = rem % 65536;
    short s1 = (short) (rem / 256);
    short s0 = (short) (rem % 256);

    ret.put(short2Byte(s3));
    ret.put(short2Byte(s2));
    ret.put(short2Byte(s1));
    ret.put(short2Byte(s0));

    return ret.array();
}

private byte [] time2Bytes(Long time) {
    ByteBuffer ret = ByteBuffer.allocate(6);
    String hex = Long.toHexString(time).toUpperCase();
    while (hex.length() < 12) {
        hex = "0" + hex;
    }

    while (hex.length() > 12) {
        hex = hex.substring(1);
    }

    try {
        for (int i = 0; i < 6; i++) {
            String strByte = "" + hex.charAt(i*2) + hex.charAt(i*2 + 1);
            short b = Short.parseShort(strByte, 16);
            if (b > 127) {
                b -= 256;
            }
            ret.put((byte) b);
        }
    }
    catch (NumberFormatException e) {
        // Exception captured for correctness
        e.printStackTrace();
    }


    return ret.array();
}

private long bytes2time(byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) {
    long l5, l4, l3, l2, l1, l0;
    l5 = byte2short(b5) * 1099511627776L;
    l4 = byte2short(b4) * 4294967296L;
    l3 = byte2short(b3) * 16777216L;
    l2 = byte2short(b2) * 65536L;
    l1 = byte2short(b1) * 256L;
    l0 = byte2short(b0) * 1L;
    return  l5 + l4 + l3 + l2 + l1 + l0;
}

private long bytes2long(byte b3, byte b2, byte b1, byte b0) {
    long l3, l2, l1, l0;
    l3 = byte2short(b3) * 16777216L;
    l2 = byte2short(b2) * 65536L;
    l1 = byte2short(b1) * 256L;
    l0 = byte2short(b0) * 1L;
    return  l3 + l2 + l1 + l0;
}

private int bytes2int(byte b1, byte b0) {
    return (int)byte2short(b1) * 256 + (int)byte2short(b0);
}

private short byte2short(byte b) {
    if (b < 0) {
        return (short) (b+256);
    }
    return (short)b;
}

private byte short2Byte(short s) {
    if (s < 128) {
        return (byte) s;
    }
    else {
        return (byte) (s-256);
    }
}

最後に、49 バイトのバイト配列を送信しています。明らかに、解析解除は非常によく似たプロセスです。これを行うには適切な方法が必要ですが、うまくいきます...これが誰かの助けになることを願っています!

4

1 に答える 1

0

ByteBufferおよびBitSetクラスを使用してメッセージの書き込みと読み取りを行うことができますが、純粋なビット操作よりも悪夢になる可能性があります (パフォーマンスに影響します)。

于 2013-07-09T10:22:51.620 に答える