在 Java 中将 DatagramPacket 转换为字节数组后对其进行解析
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10774091/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Parse a DatagramPacket after converting it to a byte array in Java
提问by InvalidBrainException
I am trying to parse a DatagramPacket that I will receive at a socket. I know the format of the packet I will receive, which is a DHCPREQUEST packet, but I don't think that really matters. For simplicity's sake, let's just consider the first six fields:
我正在尝试解析将在套接字上接收到的 DatagramPacket。我知道我将收到的数据包的格式,即 DHCPREQUEST 数据包,但我认为这并不重要。为简单起见,我们只考虑前六个字段:
First field is the "opcode", which is 1 byte.
Second field is the "hardware type" which is 1 byte.
Third, "hardware address length", 1 byte.
Fourth, "hops", 1 byte.
Fifth, "transaction identifier xid", 4 bytes.
Sixth, "seconds", 2 bytes.
第一个字段是“操作码”,它是 1 个字节。
第二个字段是“硬件类型”,它是 1 个字节。
三、“硬件地址长度”,1个字节。
四、“跳数”,1个字节。
五、“交易标识符xid”,4个字节。
六、“秒”,2个字节。
After I receive the packet, my approach is to convert it to a byte array.
收到数据包后,我的做法是将其转换为字节数组。
DatagramPacket request = new DatagramPacket(new byte[1024], 1024);
socket.receive(request);
byte[] buf = request.getData();
At this point, the packet is stored in the byte array buf
as a series of bytes. Since I know what the structure of this byte sequence is, how can I parse it? The one-byte fields are simple enough, but how about the multiple-bit fields? For example, how can I extract bytes 4 to 7, and store them in a variable named xid
?
此时,数据包buf
作为一系列字节存储在字节数组中。既然知道这个字节序列的结构是什么,那怎么解析呢?一字节字段很简单,但是多位字段呢?例如,如何提取字节 4 到 7,并将它们存储在名为 的变量中xid
?
I could manually put each byte into an array:
我可以手动将每个字节放入一个数组中:
byte[] xid = new byte[4];
xid[0] = buf[4];
xid[1] = buf[5];
xid[2] = buf[6];
xid[3] = buf[7];
But that's just tedious, and impractical for fields that are hundreds of bytes in length. The String class can parse substrings given an offset and length; is there a similar method for byte arrays in Java?
但这对于数百字节长度的字段来说只是乏味且不切实际的。String 类可以解析给定偏移量和长度的子字符串;Java 中的字节数组是否有类似的方法?
Or am I somehow making things difficult for myself?
还是我以某种方式为自己制造了困难?
采纳答案by Don Roby
The cleanest way to do something like this is probably to use the utility method Arrays.copyOfRange
.
执行此类操作的最简洁方法可能是使用实用程序方法Arrays.copyOfRange
。
回答by user207421
Wrap the byte array in a ByteArrayOutputStream; wrap a DataInputStream around that; then use the methods of DataInputStream.
将字节数组包装在 ByteArrayOutputStream 中;围绕它包装一个 DataInputStream ;然后使用 DataInputStream 的方法。
回答by Stephen C
What you do is write yourself some helper methods to extract 2 byte, 4 byte, etc values from the packet, reading the bytes and assembling them into Java short
, int
or whatever values.
你要做的就是自己写的一些辅助的方法来从包中提取2字节,4字节,等值,读取字节并将其组装成Java short
,int
或任何价值。
For example
例如
public short getShort(byte[] buffer, int offset) {
return (short) ((buffer[offset] << 8) | buffer[offset + 1]);
}
Then you use these helper methods as often as you need to. (If you want to be fancy, you could have the methods update an attribute that holds the current position, so that you don't have to pass an offset
argument.)
然后,您可以根据需要经常使用这些辅助方法。(如果你想变得漂亮,你可以让方法更新一个保存当前位置的属性,这样你就不必传递offset
参数。)
Alternatively, if you were not worried by the overheads, you could wrap the byte array in ByteArrayInputStream
and a DataInputStream
, and use the latter's API to read bytes, shorts, ints, and so on. IIRC, DataInputStream
assumes that numbers are represented in the stream in "network byte order" ... which is almost certainly what the DHCP spec mandates.
或者,如果您不担心开销,您可以将字节数组包装在ByteArrayInputStream
and a 中DataInputStream
,并使用后者的 API 读取字节、shorts、ints 等。IIRC,DataInputStream
假设数字以“网络字节顺序”在流中表示……这几乎可以肯定是 DHCP 规范所要求的。
回答by Tordek
I'm a bit late to this, but there's a ByteBuffer class:
我有点晚了,但是有一个 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();
Or, if you only need a single field:
或者,如果您只需要一个字段:
ByteBuffer b = ByteBuffer.wrap(request.getData());
int xid = b.getInt(4);