BitTorrent点对点传输协议(TCP)

3

请问消息是如何由节点进行编码、发送和接收的呢?

如果有一条消息

have: <len=0005><id=4><piece index> 

这个消息是如何发送的(以二进制形式,如何将其转换为二进制形式?)并且如何接收?

消息发送给同行的顺序是否有特定的顺序?

我已经阅读了规范,但还有一些疑问。

谢谢

3个回答

4
我将回答关于排序的问题。
通常情况下,您可以随时发送任何消息。但是有些消息有特殊规则。例如,BITFIELD消息必须尽早发送。大多数客户端按照请求的顺序发送PIECEs,但如果我没记错的话,这不是必需的。
一般来说,这些消息分为两种类型。一种是控制导向的消息,告诉对等方有关一般状态的信息(HAVE消息属于此类)。另一种是数据导向的消息,实际传输文件并从对等方请求新数据。这些消息类型是“交织的”,你发送的PIECE消息不超过16千字节,以确保控制消息可以在其中交错。一个技巧是,在发送PIECE消息后,然后按优先级发送所有控制导向的消息,然后再发送下一个PIECE消息。这样,您可以迅速告诉对方您的意图。
原始协议中还存在一个“错误”,这个错误通过FAST扩展得到解决。它有效地使每个REQUEST结果都会产生一个PIECE消息或REJECT-REQUEST消息。这是另一个排序的例子。如果您收到了针对您从未请求过的内容的REJECT-REQUEST消息,则会断开与对等方的连接。

谢谢。人们是如何发现这些东西的,因为文档很少呢? - some_id
1
嗯,你为了好玩实现了几个 BitTorrent 客户端 :) (我有两个,一个是 Erlang,一个是 Haskell)。规格很少,但你会发现在开始实现客户端时通常只有一种合理的做法。我唯一需要问的问题是“当你阻塞对等方时,你是否删除了本地的请求消息队列?”答案是肯定的,这与我提到的“错误”有关。 - I GIVE CRAP ANSWERS
我已经阅读了你的帖子,比较了两种客户端的语言。你用Erlang拥有唯一值得称赞的种子下载客户端,不错 :) 嗯,在合理方面来说,是的,我想是这样的,但我现在面临的问题是正确实现协议。从文档中并不是那么清晰明了。感谢上述提示 ;) - some_id
这不是像HTTP那样简单的协议。你可以轻松地在几个小时内建立一个基本的(非符合性)HTTP客户端。但是对于BitTorrent来说并非如此。它是一个相当复杂的协议,你将会遇到许多小细节实现它。但是这种古怪性也是使协议有趣和有趣的原因。 - I GIVE CRAP ANSWERS

3
在声明have消息之前,规范中提到:

协议中剩余的所有消息都采用<长度前缀><消息ID><有效负载>的格式。长度前缀是一个四字节大端值。消息ID是一个单个十进制字节。有效负载取决于消息。

你已经掌握了长度和ID的二进制格式。'piece index'部分是这个消息特定的有效负载。由于该消息的固定大小为5个字节,其中1个字节用于消息ID(查看其他具有相同格式的消息应该能给你一些线索),因此它应该是四个字节长。

查看其他具有相同格式的消息应该给你一个提示。这是我的问题:)。另外,例如< len = 0005 >或< len = 0001 >是什么?如果消息像这样< len = 0005 > < id = 4 > < piece index>,那么< >之间的值将被它们的二进制表示替换? - some_id
假设片段索引为7(为什么不是呢?),整个消息将是:0x000000050400000007。 - yonilevy

0
我知道这篇帖子很旧,但我写了几个Node.js脚本来帮助理解Bittorrent协议,对于任何想要了解该协议并偶然遇到这个问题的人来说应该很有帮助。
以下是主要脚本: https://github.com/liveduo/bittorrent-scripts/blob/main/3-connect-node.js 你可以轻松地在本地运行它,而且它不需要npm install,因为它没有外部依赖。
要开始,你只需要一个种子文件(即磁力链接)和一个拥有该种子文件的节点(即节点的IP地址和端口)。在repository中还有更多获取拥有种子文件的节点的脚本。
如果你需要更多帮助使一切正常工作,我在这里写了一个指南here,其中包含解释和嵌入式脚本,你可以直接在网站上运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接