在将数据报转换为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 short
, int
或任何值。
例如
public short getShort(byte[] buffer, int offset) { return (short) ((buffer[offset] << 8) | buffer[offset + 1]); }
然后根据需要随时使用这些辅助方法。 (如果你想要花哨,你可以让方法更新一个保存当前位置的属性,这样你就不必传递offset
参数。)
或者,如果您不担心开销,可以将字节数组包装在ByteArrayInputStream
和DataInputStream
,并使用后者的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);