2

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

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

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

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

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

如果我不知道长度,我无法想出解析它的方法;我应该如何在字节流中定位 id ?

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

4

4 回答 4

4

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

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 个片段的空间。那应该足够了!:-)

于 2009-06-22T21:48:58.030 回答
3

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

从描述来看,长度在消息的前4个字节中给出。

我应该如何在字节流中定位 id ?

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

于 2009-06-22T21:49:36.830 回答
3

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

于 2009-06-22T21:51:59.023 回答
1

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

于 2009-06-22T21:46:08.473 回答