4

ソケットで受け取るDatagramPacketを解析しようとしています。受信するパケットの形式であるDHCPREQUESTパケットは知っていますが、それはそれほど重要ではないと思います。簡単にするために、最初の6つのフィールドについて考えてみましょう。

最初のフィールドは「オペコード」で、1バイトです。
2番目のフィールドは1バイトの「ハードウェアタイプ」です。
第三に、「ハードウェアアドレスの長さ」、1バイト。
第四に、「ホップ」、1バイト。
5番目、「トランザクション識別子xid」、4バイト。
6番目、「秒」、2バイト。

パケットを受け取った後、私のアプローチはそれをバイト配列に変換することです。

DatagramPacket request = new DatagramPacket(new byte[1024], 1024);
socket.receive(request);
byte[] buf = request.getData();

この時点で、パケットはbuf一連のバイトとしてバイト配列に格納されます。このバイトシーケンスの構造がわかっているので、どうすれば解析できますか?1バイトのフィールドは十分に単純ですが、マルチビットのフィールドはどうでしょうか。たとえば、バイト4〜7を抽出して、?という名前の変数に格納するにはどうすればよいxidですか?

各バイトを手動で配列に入れることができます。

byte[] xid = new byte[4];
xid[0] = buf[4];
xid[1] = buf[5];
xid[2] = buf[6];
xid[3] = buf[7];

しかし、それは退屈で、長さが数百バイトのフィールドには実用的ではありません。Stringクラスは、オフセットと長さを指定してサブストリングを解析できます。Javaのバイト配列に同様の方法はありますか?

それとも私はどういうわけか自分自身のために物事を難しくしていますか?

4

4 に答える 4

4

バイト配列をByteArrayOutputStreamでラップします。その周りにDataInputStreamをラップします。次に、DataInputStreamのメソッドを使用します。

于 2012-05-27T23:42:46.573 に答える
3

このようなことを行う最もクリーンな方法は、おそらくユーティリティメソッドを使用することですArrays.copyOfRange

于 2012-05-27T13:01:39.630 に答える
2

shortパケットから2バイト、4バイトなどの値を抽出し、バイトを読み取ってJavaなどの値にアセンブルするためのヘルパーメソッドを自分で作成しintます。

例えば

    public short getShort(byte[] buffer, int offset) {
        return (short) ((buffer[offset] << 8) | buffer[offset + 1]);
    }

次に、これらのヘルパーメソッドを必要な頻度で使用します。(凝ったものにしたい場合は、引数を渡す必要がないように、メソッドに現在の位置を保持する属性を更新させることができoffsetます。)


または、オーバーヘッドを気にしない場合は、バイト配列をByteArrayInputStreamとでラップしDataInputStream、後者のAPIを使用してバイト、ショート、intなどを読み取ることができます。IIRCDataInputStreamは、数値が「ネットワークバイトオーダー」でストリームに表されることを前提としています...これはほぼ確実にDHCP仕様で義務付けられているものです。

于 2012-05-27T13:02:54.697 に答える
2

私はこれに少し遅れていますが、ByteBufferクラスがあります:

ByteBuffer b = ByteBuffer.wrap(request.getData());

byte opcode = b.get();
byte hwtype = b.get();
byte hw_addr_len = b.get();
byte hops = b.get();
int xid = b.getInt();
short seconds = b.getShort();

または、単一のフィールドのみが必要な場合:

ByteBuffer b = ByteBuffer.wrap(request.getData());
int xid = b.getInt(4);
于 2012-12-06T01:42:08.583 に答える