磁力链接的开头“magnet:?xt=urn:btih:”是什么含义?

磁力链接的开头“magnet:?xt=urn:btih:”是什么含义?

接下来先解释磁力链接本身,再介绍其为什么可以实现文件下载。

HTTP 链接的格式已被我们熟知,日常的网站访问都要用到。而磁力链接和其一样,都是符合 IETF URI[1] 标准的。具体如下图所示:

磁力链接也分为协议名称、冒号、路径、问号、参数列表几部分。其中,“路径”固定为空字符串,因为在P2P下载的上下文中用不到这个概念。

接下来逐个介绍磁力链接的关键参数[2]。

1.2.1 xt

xt(eXact Topic)用于通过标识来明确指定想要下载的目标文件。

示例:

格式:

第一部分:资源标识类型。如何在网络中标识一个资源是一个老生常谈的话题,由此,产生了 URI (Uniform Resource Identifier) 标准[1]。URI 下有两个思路:

磁力链接通常使用哈希值来标识一个资源,属于 URN 思路,所以 xt 参数的第一部分通常是“urn”。

第二部分:值类型。磁力链接被设计出来就是为了定一个标准,用来兼容各种下载协议。所以需要有这第二部分来指明后面值得含义。常见的值类型有 btih (BitTorrent info hash)、btmh (BitTorrent info hash v2)、ed2k (eDonkey2000) 等等。

第三部分:值。这部分是具体的哈希值,对应了一个具体的资源。

另外,xt 参数还支持在一个磁力链接中指定多个文件,形如:

1.2.2 dn

dn (Display Name) 为目标资源指定一个文件名,用于在客户端上的展示。

比如下面这个磁力链接:

其在 uTorrent 客户端的展示如下:

1.2.3 so

目标资源中可能会包含多个文件,而我们也可能只想下载其中的几个,而非全部,此时,so (Select-Only) 参数就可以发挥作用,即通过其指定要下载第几个文件(从 0 开始)[4]。

示例:

在此以 Bittorrent 为例,介绍 P2P 下载是如何一步步发展到仅需“磁力链接”的。

常见的中心式下载的架构如下:

一组服务器负责所有客户端的下载请求。服务端的出口带宽将面临极大考验,很有可能成为下载速率的瓶颈。

而 Bittorrent 则是另一个思路:当一个客户端完成了一个文件部分数据的下载后, 它就可以转而成为这部分数据的“源头”,为其他客户端提供下载服务;系统中所有客户端均可以成为数据提供者,从而形成了一个“去中心化”的系统。此时,单节点的出口带宽几乎不会成为下载速率的瓶颈。

Bittorrent 客户端完成下载任务的算法很清晰,其核心就是在回答如下两个问题:

2.1.1 Bittorrent 客户端如何确定需要下载哪些数据?

Bittorrent 下载始于“种子文件”(后缀为 .torrent)。该文件为客户端描述了下载任务,包括文件名、文件大小、文件块切分大小以及校验下载数据是否正确的 hash 值等等。

种子文件的内容是一个 Map(经过 Bencode 编码)[5],其核心字段如下:

2.1.2 Bittorrent 客户端如何知晓需要找谁进行下载?

“种子文件”中包含了 Tracker 的地址,客户端可通过询问 Tracker 来获知各文件块可以找哪些节点下载。

那问题来了:Tracker 是如何得到这些信息的呢?答案是 Bittorrent 客户端会向 Tracker 上报自己完成了哪些数据的下载[5]。

根据上文描述,“第一阶段”的 Bittorrent 集群结构如下:

可以看到整个系统仍然存在一个“中心”,即 Tracker。这会引出一些顾虑:

这些都违背了 Bittorrent 协议去中心化的初衷。为此,Bittorrent 协议引入了 DHT (Distributed Hash Table)。

2.2.1 什么是 DHT ?

从 DHT 的全称“Distributed Hash Table”可以看出,其本质就是将数据分布到多台机器上的哈希表[6]。

DHT 需要比普通哈希表多回答一个问题:给定一个 Key,如何判断要去哪台机器取 Value?

虽然在 DHT 思想下有多种不同的具体算法(比如 Consistent Hashing[7] 等等),但它们都保证了同一个属性:一台机器,要么是存储了目标 Key - Value,要么其知晓离目标 Key 所在机器更”近“的下一台机器。

那么定位 Key 的过程就是一个“路由”的过程:

2.2.2 DHT 如何应用于 Bittorrent ?

至此,已不需要独立的 Tracker 系统,所有的客户端加在一起就构成了一个存储 DHT 的集群。系统结构如下图:

DHT 的 Value 用于“存储下载任务的信息(之前“种子文件”包含的数据)”和“文件的各部分可以找哪些节点下载(之前 Tracker 系统所维护的信息)”。

DHT 的 Key 则是一个下载资源对应的 Hash 值。

现在,仅凭一个 Hash 值即可查到相关信息的查询,无需种子文件,无需独立的Tracker;此时仅靠磁力链接即可完成下载任务。

本文介绍了磁力链接的格式,并简要拆解了磁力链接生效的核心原理。

才疏学浅,未能窥其十之一二,欢迎大家交流补充。