当它们重叠时如何将块分成一块

How to divide block in piece when they overlap

一些输入我正在寻找构建一个简单的最小 bittorrent 客户端。 我现在阅读了 2-3 天的协议规范。

这是我到目前为止的理解。假设 torrent 的 片段长度 26000 bytes,并且根据非官方规范 块大小 16384。像这样。

现在根据请求,一块消息看起来像这样

piece 0 
block offset 0
block length 16484

到目前为止一切顺利。

现在,对于在片段 0 和片段 1 中重叠的下一个块,请求应该是什么样的

piece 0  ## since the start of byte is in piece 0 use piece 0 instead of piece 1
block offset 16384
block length 16384

现在在接收端我需要重新创建 26000 字节的片段,以便我可以将其与片段(哈希)进行比较以匹配片段的正确性。

我的理解正确吗?

此外,我假设块验证失败,可能是因为第一个块,即块 0(有故障或损坏) 然后我应该重新排队 Block 0 和 Block 1(顺便说一句,这是有效的,也是第 1 部分的一部分)以再次重新传输。

现在突然间,块和块分布变得有点复杂,然后我假设它是。我希望有一个更简单的解决方案。

任何想法

块中的最后一个块可能小于传输块大小。 IE。 26000 - 16384 = 9616 字节应在第二个 PIECE 消息中请求。一旦收到所有 26000 字节,就应该计算 SHA-1 哈希值,并将其与元信息字典 pieces 部分的相应校验和进行比较。如果校验和不匹配,您将无法知道哪个块包含无效数据,应该从该块重新下载所有块。

我的建议是不要依赖作品的某些特定分区,因为: 1) peers 在请求数据时可能使用不同的传输块大小 2) SHA-1 算法是基于块的,消化器最好使用更大的块大小(否则计算会花费更多时间)

一件作品的适当抽象应该是具有以下方法的通用 data range

  • read(from:int, length:int):byte[]
  • write(offset:int, block:byte[]):()

然后您将能够 read/write 任意数据子范围。

客户普遍接受的最大块大小为16KiB。客户可以自由提出较小的要求。

块通常是 16KiB 的倍数,但当前的规范不要求它(这随 BEP52 改变)并且有些人使用质数或类似的东西来取乐,所以它们确实存在于野外.

块仅存在于您需要多个请求才能获得大于 16KiB 的完整块的意义上。换句话说,块与您决定请求的任何东西都是一样的。您可以请求 500 个字节,然后是 1017 个字节,然后是 13016 个字节,...直到您得到一个完整的片段。它们是片段中的任意细分 - 没有重叠 - 您需要在下载片段开始和完成片段之间进行跟踪。

它们不参与散列,不考虑 HAVE 或 BITFIELD 消息。只有 REQUEST、PIECE、CANCEL 和 REJECT 消息与块有关。除了块,您还可以将它们称为 子片偏移长度元组 或类似的东西。

Will use the more distinct term 'chunk' instead of the ambiguous 'block'.


  • 洪流分片

  • 一块分成几块

  • 一块切一块。

Torrent 在创建时被分成多个部分。使用 Request 消息,一块又被下载的 BitTorrent 客户端进一步分成块。
客户端如何从一块中切出块并不重要,只要没有单个块大于 16 KB(16384 字节)。
划分一块的最简单和最合理的方法是将其划分为尽可能少的块,将其划分为 16 KB 的块,并在必要时让该块的最后一块更小。


The Request message format: <len=0013><id=6><Piece_index><Chunk_offset><Chunk_length>

  • <Piece_index > integer specifying the zero-based piece index
  • <Chunk_offset> integer specifying the zero-based byte offset within the piece
  • <Chunk_length> integer specifying the requested number of bytes



请求块时:

  • 整个块必须在 Piece_index,
    指定的块内 即 Chunk_offset+Chunk_length 必须小于或等于该特定片段的大小*。
  • Chunk_length 不能大于 16 KB(16384 字节)并且必须至少为 1 个字节
  • 收到请求的节点必须有 Piece_index
  • 指定的片段

如果不满足任何条件,接收请求的对等方将关闭连接。

* 除了最后一个是 info 字典中定义的 'piece length' 之外的所有片段。
最后一块的大小可以计算为:
size_last_piece = size_of_torrent - (number_of_pieces - 1) * 'piece length'