我试图解析,我会收到在插座的DatagramPacket。 我知道我包将接受,这是一个DHCP请求报文的格式,但我不认为这真的很重要。 为简单起见,我们只考虑前六个领域:
第一字段是“操作码”,这是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 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);