BitTorrent 中的 Extension Protocol 具体是什么?

BitTorrent 中的 Extension Protocol 是一种用于扩展和增强 BitTorrent 下载协议功能的机制。它允许客户端通过发送和响应与标准协议不同的消息来进行通信。这些消息可以实现新的功能,如 DHT(分布式哈希表)交换、 PEX(对等交换)以及支持更高级别的加密。

Extension Protocol 在 BitTorrent 协议中起着至关重要的作用,因为它允许客户端进行更有效和更可靠的数据交换,并提供了更好的隐私和安全性。例如,DHT 支持无需 Tracker 即可查找其他已连接到网络的对等方;而 PEX 则允许客户端直接与其他客户端通信,从而使数据交换更加稳定和可靠。

协议简介

这个协议的目的是为 BitTorrent 协议的扩展提供一个简单而轻量的传输方式。支持这个协议可以很容易地添加新的扩展功能,而不会干扰标准的 BitTorrent 协议或不支持你想要添加的扩展功能的客户端。换句话说,这个协议提供了一种灵活、可扩展的机制,使得开发者能够在不影响其他用户的情况下,对 BitTorrent 协议进行个性化的扩展和定制。

在 BitTorrent 协议中,为了向其他支持的客户端传播自己,会使用保留字节中的一个字节。其中,用于扩展协议的字节是从右边开始数的第 20 个(从 0 开始计数)。因此,可以通过表达式(reserved_byte[5] & 0x10)来检查客户端是否支持扩展消息传输。这个表达式的含义是,将保留字节中的第 5 个字节与 0x10 进行按位与运算,如果结果不为 0,则表示客户端支持扩展消息。

建立对协议的支持后,客户端应该支持 1 条新消息:

name id
extended 20

这个消息与其他 BitTorrent 消息一样,以 4 字节的长度前缀和一个单字节的标识符(在本例中为 20)发送。在消息有效负载的开头,有一个单字节的消息标识符。该标识符可以引用不同的扩展消息,但只指定了一个 ID,即 0 。如果 ID 是 0,则表示这个消息是一个握手消息,下面会进行描述。一般扩展消息的布局如下所示(包括 BitTorrent 协议使用的消息头):

size description
uint32_t 长度前缀。指定整个消息的字节数。(大端序 1)
uint8_t bittorrent 消息 ID, = 20
uint8_t 扩展消息 ID 。 0 = 握手,>0 = 握手指定的扩展消息。

握手消息

握手消息的有效负载是一个 bencoded 字典。字典中的所有项都是可选的。客户端应该忽略字典中未知的名称。字典中的所有部分都区分大小写。字典中定义了以下项目:

name description
m 支持的扩展消息字典将每个扩展消息的名称映射到一个扩展消息 ID 。对这些 ID 唯一的要求是,没有两个扩展消息可以共享同一个 ID 。将扩展号设置为零意味着该扩展未被支持/禁用。客户端应忽略其不识别的任何扩展名。扩展消息 ID 是用于将扩展消息发送到发送此握手的同行方的 ID 。也就是说,这些 ID 是特定于此特定对等体的本地 ID 。

这里列出了一些实现可能选择支持的项目:

name description
p 本地 TCP 监听端口。允许每一方了解另一方的 TCP 端口号。请注意,接收连接的一方不需要发送此扩展消息,因为其端口号已知。
v 客户端名称和版本(作为 UTF-8 字符串)。这是比依赖对等方 ID 编码更可靠的识别客户端的方法。
yourip 一个包含 IP 地址紧凑表示的字符串,用于表示此节点看到您的 IP 地址。也就是说,这是接收方的外部 IP 地址(不包括端口)。它可以是 IPv4(4 个字节)或 IPv6(16 个字节)地址。
ipv6 如果此节点具有 IPv6 接口,则这是该地址的紧凑表示(16 个字节)。客户端可能更喜欢通过 IPv6 地址进行连接。
ipv4 如果此节点具有 IPv4 接口,则这是该地址的紧凑表示(4 个字节)。客户端可能更喜欢通过 IPv4 地址进行连接。
reqq 一个整数,表示此客户端支持的未完成请求消息数量,而不会丢失任何消息。在 libtorrent 中,默认值为 250 。

握手字典还可以包括扩展的握手信息,例如支持加密头部或任何可能的内容。

以下是握手消息负载的示例内容:

Dictionary
m Dictionary / LT_metadata······1 / ut_pex··················2
p 6881
v “µTorrent 1.2”

并以编码形式:

d1:md11:LT_metadatai1e6:µT_PEXi2ee1:pi6881e1:v13:\xc2\xb5Torrent 1.2e

为了避免扩展名不小心发生冲突,应该在扩展名前加上一个或两个字符的代码,以标识引入扩展的客户端。这适用于扩展消息的名称以及放在顶层字典中的任何其他信息。除非由本规范定义,否则所有一字节和两字节标识符均无效。

此消息应在标准 bittorrent 握手后立即发送到支持此扩展协议的任何节点。在连接的整个周期内,可以多次发送握手消息,发送方不应断开连接。实现可以选择忽略后续的握手消息(或其部分)。

随后的握手消息可用于在不重新启动连接的情况下启用/禁用扩展。如果节点持在运行时更改扩展,则应注意 m 字典是累加的。它包含扩展列表的实际更改就足够了。要在运行时禁用对 LT_metadata 的支持,而不影响任何其他扩展,应发送此消息:d11:LT_metadatai0ee 。如上所述,值 0 用于关闭扩展。

必须为每个节点存储扩展 ID,因为每个节点可能具有相同扩展的不同 ID 。

该规范故意没有指定任何扩展,例如节点交换或元数据交换。该协议仅是 bittorrent 协议实际扩展的传输方式,上面的示例中命名的扩展(例如 p)只是可能扩展的示例。

合理的依据

为了避免使用全局消息 ID 注册表,扩展消息的 ID 在握手过程中被定义的原因是为了确保扩展消息名称具有唯一性,这样做比使用全局注册表更容易。惯例是在扩展消息名称上使用两个字母前缀,该前缀将标识最先实现该扩展消息的客户端。例如,LT_metadata 由 libtorrent 实现,因此它具有 LT 前缀。

如果支持扩展的客户端可以决定其接收到的消息将具有哪些数字,那么这些数字就是该客户端内的常量。也就是说,它们可以用于 switch 语句。对于另一端来说,存储一个包含每个消息期望的 ID 的数组并在每次发送扩展消息时使用该数组进行查找非常容易。

使用字典而不是使用(用于隐式分配索引号扩展的)数组的原因是,如果客户端想要禁用某些扩展,ID 号码将会改变,它将无法使用常量(因此,不能在 switch 中使用它们)。如果消息 ID 直接映射到 BitTorrent 消息 ID,则还可以将握手中的扩展映射到具有固定消息 ID 的现有扩展。

使用单个字节作为扩展消息标识符的原因是为了遵循 BitTorrent 规范的单个字节消息标识符。这被认为足够了。它不会限制扩展的总数,只会限制同时使用的扩展数。

使用单个字节标识符作为标准化握手标识符的原因是:1)主线 DHT 使用单个字节标识符;2)节省带宽。更长消息的唯一优点是使协议对人类更易读,但是 BT 协议并不是设计成人类可读的协议,所以为什么要费心呢。

总的来说,Extension Protocol 是 BitTorrent 协议的一个重要组成部分,它为用户提供了更多的功能和更好的使用体验。

参考链接

来源链接

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容