在将数据报转换为Java中的字节数组之后解析它

我正在尝试解析我将在套接字上收到的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中的字节数组有类似的方法吗?

或者我在某种程度上让自己变得困难?

做这样的事情的最干净的方法可能是使用实用程序方法Arrays.copyOfRange

将字节数组包装在ByteArrayOutputStream中; 将DataInputStream包装起来; 然后使用DataInputStream的方法。

你要做的就是给自己编写一些辅助方法,从数据包中提取2字节,4字节等值,读取字节并将它们组装成Java shortint或任何值。

例如

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

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


或者,如果您不担心开销,可以将字节数组包装在ByteArrayInputStreamDataInputStream ,并使用后者的API读取字节,短路,整数等。 IIRC, DataInputStream假设数字在流中以“网络字节顺序”表示......这几乎肯定是DHCP规范要求的。

我有点迟到了,但是有一个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);