Java对象到UDP byte []

时间:2016-10-31 17:36:14

标签: java udp bytebuffer

我正在尝试创建UDP客户端服务器。我已经能够通过执行以下操作来阅读消息:

我收到的消息是BIG_ENDIAN,结构如下:

UINT8  type;           
UINT8  flags;              
UINT16 len;                
UINT32 sequenceN;          
UINT16 startIdx;         
UINT16 endIdx;

相应的Java对象是:

short type;
short flags;
int len;
long sequenceN;
int startIdx;
int endIdx;

要从UDP转换为Java,请使用以下命令:

typeArray = Arrays.copyOfRange(msg, 0, 1);
type = Util.reassembleShort(typeArray);
flagsArray = Arrays.copyOfRange(msg, 1, 2);
flags = Util.reassembleShort(flagsArray);
lenArray = Arrays.copyOfRange(msg, 2, 4);
len = Util.reassembleInt(lenArray);
seqArray = Arrays.copyOfRange(msg, 4, 8);
sequenceN = Util.reassembleLong(seqArray);
startArray = Arrays.copyOfRange(msg, 8, 10);
startIdx = Util.reassembleInt(startArray);
endArray = Arrays.copyOfRange(msg, 10, 12);
endIdx = Util.reassembleInt(endArray);

要将字节数组部分重新组合成Java对象,我使用以下内容(AKA调用上面的Util.reassemble *):

ByteBuffer buffer = ByteBuffer.wrap(input);
buffer.order(ByteOrder.BIG_ENDIAN);
short result = ((short) (buffer.get() & 0xff));

ByteBuffer buffer = ByteBuffer.wrap(input);
buffer.order(ByteOrder.BIG_ENDIAN);
long result = ((long) buffer.getInt() & 0xffffffffL);

内部

ByteBuffer buffer = ByteBuffer.wrap(input);
buffer.order(ByteOrder.BIG_ENDIAN);
int result = (buffer.getShort() & 0xffff);

字符串

String result = new String(removeStringGarbage(input), Charset.forName("US-ASCII"));

这很有效。我的问题是......如何进行反向操作并将对象放入正确大小的字节缓冲区以便在UDP上发回?

1 个答案:

答案 0 :(得分:0)

如果您必须准确地遵循预先存在的线上二进制格式,请尝试“Kaitai Struct”(http://kaitai.io/)。

如果您能够更改序列化格式(即您可以控制它),请查看“协议缓冲区”:https://developers.google.com/protocol-buffers/docs/javatutorial

在这两种情况下,使用预先存在的库,以声明方式描述二进制协议,将为您节省大量的时间和精力, 并且通常会产生更强大的代码(因为代码生成器可以更好地处理损坏的数据并且永远不会进行拼写错误)。

使用“协议缓冲区”,您还可以获得可扩展性,即您可以在保持向后兼容性的同时发展协议。

如果您仍想手动序列化/反序列化数据, 只需使用 ByteBuffer的 putX 方法,如下所示:

 buffer.put((byte)(type & 0xFF));
 buffer.put((byte)(flags & 0xFF));
 buffer.putShort((short)(len & 0xFFFF));
 buffer.putInt((int)(sequenceN & 0xFFFFFFFF));
 buffer.putShort((short)(startIdx & 0xFFFF));
 buffer.putShort((short)(endIdx & 0xFFFF));

put操作类型应该与你的二进制字段大小匹配(即UINT8的put(),UINT16的putShort,UINT32的putInt ...),你必须对它应用一个适当的掩码(即0xFF为简称,0xFFFF为int)等)