解析可变长度的消息

时间:2009-06-22 21:37:06

标签: java parsing network-protocols inputstream bittorrent

我正在通过此spec使用Java实现BitTorent协议。在消息部分,所有消息都是固定长度,除了其中2个;对于其中一个,它是握手后唯一的可变消息,所以我可以检查其他消息,并假设当没有其他消息满足时它是一条消息。但是对于以下消息

bitfield: <len=0001+X><id=5><bitfield>
     

位域消息只能在握手序列完成后立即发送,并且在发送任何其他消息之前发送。它是可选的,如果客户端没有碎片,则无需发送。

     

位域消息是可变长度,其中X是位域的长度。有效负载是表示已成功下载的部分的位域。第一个字节中的高位对应于片段索引0.清除的位表示丢失的片段,而设置的位表示有效且可用的片段。最后的备用位设置为零。

     

错误长度的位域被视为错误。如果客户端接收到不正确大小的位域,或者如果位域设置了任何备用位,则客户端应断开连接。

如果我不知道长度,我无法想出解析它的方法;我怎么能在一个字节流中找到id?

编辑:在位域消息的有效负载中,对于torrent文件中的每个片段,消息的长度为0或1,消息的长度将根据种子内容的大小而变化。所以我认为我不能假设片段的数量总是适合5个字节的数字。

4 个答案:

答案 0 :(得分:3)

id字段的四个字节之后,len字段将始终是消息的第5个字节。您可以执行以下操作:

DataInputStream stream;

// ...

int    length  = stream.readInt();
byte   id      = stream.readByte();
byte[] payload = new byte[length - 1];

stream.readFully(payload);

实际上,这应该适用于任何消息,因为它们都具有相同的len + id标题。

编辑:“所以我认为我不能假设作品的数量始终符合5个字节的数字。”

四字节长度字段可以处理有效负载中最多2 ^ 32-1个字节,每字节8位,为您提供34,359,738,360个空间。那应该够多了! : - )

答案 1 :(得分:2)

  

我无法想出解析它的方法   如果我不知道长度;

根据描述判断,长度在消息的前4个字节中给出。

  

我应该如何找到一个id   字节流?

看起来id是每个消息中的第5个字节,就在长度字段之后。因此,在完成解析上一条消息后,您只需要查看前5个字节。

答案 2 :(得分:2)

在您引用的规范的前面,我读到:'长度前缀是一个四字节的大端值。'。我把它读作:读取接下来的四个字节,将它们转换为int,这应该是你的长度。如果您不熟悉字节到内部转换过程,我使用了与this类似的东西。

答案 3 :(得分:1)

我没有详细阅读规范,但没有明确知道可变长度字段的长度或某些终止分隔符,我也看不到你如何处理它。 bitfield=<len=0001+X>不是是否表示您告知(可变)长度预先