4

我正在尝试解析我将在套接字处收到的 DatagramPacket。我知道我将收到的数据包的格式,即 DHCPREQUEST 数据包,但我认为这并不重要。为简单起见,我们只考虑前六个字段:

第一个字段是“操作码”,它是 1 个字节。
第二个字段是 1 个字节的“硬件类型”。
三、“硬件地址长度”,1字节。
四、“跳”,1个字节。
五、“交易标识xid”,4字节。
第六,“秒”,2个字节。

收到数据包后,我的方法是将其转换为字节数组。

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

此时,数据包buf作为一系列字节存储在字节数组中。既然我知道这个字节序列的结构是什么,那我该如何解析呢?一字节字段很简单,但是多位字段呢?例如,我如何提取字节 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

您所做的是自己编写一些辅助方法来从数据包中提取 2 字节、4 字节等值,读取字节并将它们组装成 Javashortint任何值。

例如

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

然后,您可以根据需要经常使用这些辅助方法。(如果你想花哨,你可以让方法更新一个持有当前位置的属性,这样你就不必传递offset参数。)


或者,如果您不担心开销,您可以将字节数组包装在ByteArrayInputStream和 aDataInputStream中,并使用后者的 API 来读取字节、短裤、整数等。IIRC,DataInputStream假设数字在流中以“网络字节顺序”表示......这几乎可以肯定是 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 回答