[往日之影]2 浅谈P2P下载

Steven-Zhl 头像
[往日之影]2 浅谈P2P下载

往日之影系列第2篇,想聊一聊P2P下载,也就是我们通常说的磁力下载。

<优美中国话>,P2P这个词被那些搞网络借贷的搞臭了。需要注意的是,P2P原意是Peer-to-Peer Network的缩写,指**对等网络**。

引子

  • 其实直到现在,磁力下载还活跃在很多方面,说它落寞有些夸张,但随着互联网的不断发展,它确实早已不再主流。
  • 现如今,依托于网络、云计算、cdn的发展,众多的网盘、云服务做的已经足够好,它们能够提供更可靠的文件存储、更稳定的数据传输服务——这些优点是传统P2P下载难以企及的。而以P2P下载为主业的企业,能活到现在,要么早早布局了云计算,要么靠的就是你懂的资源。
  • 但咱们也不成败论英雄,今天咱们从更偏技术、更偏历史的角度来聊聊P2P下载及其相关技术,单是P2P下载的故事就已经十分精彩了。

在P2P下载出现之前

  • 与现在大多数人觉得http下载合理,P2P下载古老而陌生的印象不同,http毕竟是互联网支柱一般的传输协议,其实出现时间更早[1],而最早基于P2P的下载服务Napster的出现已经是1999年了。所以在互联网早期,人们想要下载,通常只能依靠ftp或http。
  • 回想一下,20年前的互联网,无论是家庭网络的线路还是服务器的带宽其实都是非常糟糕的(不过在中国主要还是服务器忙不过来)。并且在那时下载技术也远不如现在这么方便——那时候的下载器还没有标配断点续传、多线程下载这种最常见的特性,就连下载器都没什么好选的,一般就Internet Explorer另存为。
  • 但相比于网络建设,当时软件上的发展来的更早——主要是并行下载的前提条件都已经准备好了。在中国互联网早期,“网络蚂蚁”就凭着多线程(并行下载)[2]一举成名。
    • 其实关于这个我还是懂一些的(曾经自己手搓过多线程下载器的,嘿嘿)。并行下载的条件首先是服务器要能够返回文件大小(通常是Head请求的返回头信息的Content-Length字段),其次是能够响应请求头中的Range字段,按照指定的范围返回数据。当这两点都满足后其实就可以实现并行下载了(但这两个要求已经分别在HTTP/1.0和HTTP/1.1支持了)。

    HEAD请求头信息

    • 实现上就是下载器根据Content-Length的长度,划分单个线程的下载范围,然后让每个线程异步下载自己的那部分数据,最后合并数据就可以了。
    • 网络蚂蚁的并行下载数是5,这意味着一台电脑同时向服务器创建了5个连接。假设服务器向每个连接返回数据的速度都相同,那么这台电脑的下载速度相当于同时下载的其他用户的5倍,抢网速能力十分显著。而后又出现一个同类软件“网际快车”,可以视为网络蚂蚁的改进版,线程数翻倍、增添了更多实用功能、再加上网络蚂蚁的作者后来放弃了更新,网际快车很快取代了网络蚂蚁[3]
  • 但不知道你有没有发现问题——服务器的吞吐量并没变,改变的只是你分得的带宽占比。而当每个人都用上快车后,占比重新平均,快车也就变慢车了。难道除了慢慢等服务器建设换新,我们就没办法获得更高的网速了吗?
  • 啪,基于P2P网络的下载方式诞生了。

什么是P2P网络

  • 在聊具体的软件和协议之前,我们要先聊一聊什么是P2P网络(对等式网络),和传统的中央网络系统对比着来会更容易理解。

中央网络&P2P网络

  • 上面这张图严格来讲是两种网络拓扑,左边的是中央网络系统,也就是星型结构;而右边的P2P网络系统则是非常典型的网状结构,并且在P2P网络中,每个结点都既是客户端也是服务器,这就是对等网络的含义。
  • 相比于中央网络系统,P2P网络的特点在于自由、去中心化,用户的数据传输将不再依赖于中央服务器,而是直接与其他用户进行数据交换。也正是因为这个,使得用户间能通过更广泛的网络信道传输数据,解决了服务器带宽有限的问题。

多说一句,包括上期和这期,我已经连续好几次提到“去中心化”了。确实,这是个很好的构想——内容的生产不再局限于少数人、内容的分发不再依赖于少数服务器,大家都能更平等、自由地参与互联网的建设。这听起来就好像:

公平

但在实际中呢,更多可能是:

胆子

总之我不好评价,去中心化的发展还是任重而道远啊。

P2P下载的发展史

这边就不区分软件和协议了,混在一起按照时间线来聊。

eDonkey(电驴):应用&协议

电驴电驴
  • 其实相比于现在大家最熟知的BitTorrent协议,最早出现的是Ed2k协议。
  • 最初,eDonkey以及Ed2k协议由MetaMachine公司开发,eDonkey是一个基于P2P网络的文件分享客户端,而Ed2k是其使用的协议[4]
  • 在eDonkey中,用户真正实现了上图中P2P网络的结构:每个用户机既是客户端也是服务器,无需依赖中央服务器。
  • 相比于这个客户端,我觉得Ed2k协议更值得聊聊——它应该是最早、最典型的P2P协议了,之后的很多同类协议都承袭了它的设计思想,直到现在偶尔还能见得到Ed2k链接。
  • Ed2k协议的特点
    • 哈希检验:该协议使用eD2k Hash(一种混合MD4摘要算法)识别文件。相当于使用文件自身的内容来标识文件,而不是文件名或地址(URL),这种设计理论上使得P2P网络不再需要中心索引服务器(虽然eDunkey仍然有),同时这段哈希还可以用来校验文件,之后大多数P2P协议都采用了类似的设计。
    • 动态下载:对于大于9.28MB的文件,它在下载完成前将其分割,也就是动态下载或者说“断点续传”,这有利于网络环境不好时尽量提高已下载数据的利用率。
    • 排队系统和信誉系统:从客观来讲,这两种机制确实能提高整个P2P网络的效率,但从主观来讲,这变相拉低了很多用户的体验,所以在之后的P2P网络中,大多数协议都没有使用这种机制(除了PT)

eMule(电骡):应用

  • 其实相比于电驴,eMule值得聊的就少了很多。eMule并没有什么独创的东西,它最大的亮点是能够同时连接eDonkey和Kad网络,并且开源,除此之外对eD2k链接做了一些定制化。
  • 但目前来说,Kad网络和eDonkey网络其实都已经没落了,所以eMule就不展开聊了。

FlashGet(快车/网际快车):应用

快车快车
  • 快车并不是一种协议,而单纯是个下载器,和现在很多人在用的Aria2或者Motrix类似,它是一个支持HTTP、FTP、Bt、eMule(虽然是后续更新后才支持的)等多种协议的通用下载器。同样的,它也支持多线程下载以及续传。它没有什么独创的东西,但在当时,它称得上是功能最全的下载器了。
  • 也是因为它的功能足够全,加上它是国产软件,本地化做的好,因此在世纪初快车占据了相当大的国内市场。照这么发展下去,下载器领域本不应该有迅雷的什么事的,但事实却是这款软件最终以一种相当戏剧化的原因没落了[5]
    • FlashGet由作者侯延堂在业余时间开发,并一直在维护更新,曾一度所向披靡。但就在这软件蒸蒸日上的时候,《魔兽世界》上线了,作者沉迷游戏无法自拔。
    • 在那个百家争鸣的时代,这款软件却因此经历了长达一年的停滞期,这本身就是个十分危险的信号。随后P2P横空出世,迅雷等其他软件迅速跟进,快车却迟迟没能更新,这成为扭转局势的关键因素。虽然后来在3.0版本中,快车加入了P2P下载功能,但已经无法挽回败局了。

BitTorrent

几种P2P协议链接的格式

算是小科普吧

eD2k格式

  • 一个典型的Ed2k链接格式如:ed2k://|file|<文件名>|<文件大小>|<哈希值>|/
  • 链接中包括了许多字段,使用|分隔,前4个字段固定分别是文件名文件大小哈希值和用于结束的/
  • 但在此之后还可以再加一些可选字段:
可选字段 字段含义 说明
sources 来源 指定文件的来源,格式为\|sources,<IP或主机名:端口> \|
s Http来源 同上,但格式为\|s=<Http地址>\|
h 根Hash值(eMule扩展参数) 指定文件的根Hash值,可用于文件传输时的纠错,格式为\|h=<根Hash>\|

eD2k Hash算法

以下内容摘录自eD2k链接 - 维基百科[6]

eD2k Hash 算法是一种MD4算法的变体。其函数是一个MD4 Hash列表(MD4 Hash List)的MD4根Hash,但与MD4 Hash的结果不同:

文件数据被分割成多个9500KB的chunks块(9728000字节或大约9.28MB)和剩余的一个chunk。每个chunk都要计算128-bit MD4 校验和。如果文件长度正好是9500KB的整倍数,剩余的大小为0的chunk依然存在于Hash列表的末尾。将这些chunk的MD4校验和按顺序联合起来,并使用MD4计算Hash,可得到eD2k Hash。对于仅由一个chunk组成的文件(即文件大小小于9500KB),MD4和eD2k Hash是完全相同的。

这种方法可以直接将Hash列表与原eD2k Hash进行验证,而无需使用文件块来验证。

eD2k Hash运算示意图

Magnet格式

  • 一个常见的磁力链接的格式如:magnet:?xt=urn:[散列算法]:[哈希值]&xl=[字节大小]&dn=[文件名(已编码URL)]
  • 链接中同样包括了许多字段,但与eD2k不同的是,它的字段使用&分隔,指定值时使用=,这与Http的Get传参形式相同,相比于容易被转义的|符号显得更规范;同时字段没有顺序要求(但通常最开始的是xt)
字段 可选/必选 字段含义 说明
magnet:? 必选 协议头 标识链接使用的协议,固定值
xt 必选 exact topic 指定文件的哈希算法和哈希值,格式为urn:[散列算法]:[哈希值]
urn意为“Uniform Resource Name”,固定值;
[散列算法]是指定的哈希算法,最常见的是btih,意为“BitTorrent Info Hash”;
[哈希值]是文件的哈希值,btih类型对应的哈希值是使用SHA-1算法计算的
xl 可选 exact length 指定文件的大小,单位为字节
dn 可选 display name 指定文件名,已编码URL
tr 可选 tracker 指定tracker服务器的地址,可以有多个,使用&tr=分隔
as 可选 Acceptable Source 指定可接受的来源,可以有多个,使用&as=分隔
  • 可以注意到,Magnet协议是支持多种哈希算法的,这也算是一个优点,MD4摘要算法无论怎么说还是是太旧了(最早提出于1990年[7]),Magnet这么设计,相当于为以后更新的哈希算法预留了空间。
  • 但实际使用中,Magnet协议的哈希算法几乎都是btih,主要是因为就目前来说,此处的哈希值仅用来验证文件,SHA-1算法已经足够了。

什么是Tracker?

  • Tracker是一种服务器,用于协调不同用户之间的文件共享。
  • 当你下载或分享一个使用BitTorrent协议的文件时,你的下载器(比如qBitTorrent)会与Tracker服务器通信。
  • Tracker 记录了参与文件下载的所有用户和它们的上传和下载情况,以便协调文件块的交换。这有助于提高文件下载的效率和速度。

什么是DHT?

DHT(Distributed Hash Table),分布式哈希表,是一种通过哈希函数将键值对映射到网络节点上的技术。它可以在对等网络中实现高效的数据存储与检索,同时具备自动负载均衡和容错能力。DHT被广泛应用于文件共享、网络资源定位以及分布式计算等领域。[9]

多说一句,这个参考的CSDN博客写的很不错,质量很高,有计算机网络基础的读者值得一看。

  • 设想一下,假如在没有DHT(或者DHT记录为空)、也没有Tracker服务器指定的情况下,你的客户端只能通过分布式网络中,以类似于广播的形式,“漫无目的”地寻找资源。

    你可以理解为逐个敲门去问:“你有这个资源吗?”“没有啊,好吧,谢谢”这个过程,这个效率必然是不够高的。

  • 简单来讲,DHT是一种典型的以空间换时间的策略,它将先前进行磁力下载时收集到的资源(通常就是指的“正在做种”的资源)的哈希映射到网络节点,使得之后在进行下载是可以“有的放矢”——如果你要下载的文件的哈希已经存在DHT中,则可以直接根据记录,找到可用资源。

    这种设计不由得让我想到另外两个异曲同工的东西:路由表和host文件,不过这又是其他的故事了….

  • 这也恰好解释了两个磁力下载时的细节:
    1. 为什么经常会挂一个Ubuntu镜像来做种:Ubuntu是个非常热门的资源,有很多客户端都会请求它,在别人找你下载的过程中便会交换做种的资源,构建DHT记录。时间一长,你的DHT文件里便会记录了很多的记录。不过通常来说,DHT文件的大小也就在几MB到几十MB之间,对电脑来说完全构不成负担。
    2. 为什么DHT文件只有在相近的网络中才可以通用:因为网络拓扑必然会受到现实中的网络线路影响,两台电脑所在的实际环境越接近,那么在对等网络中两台电脑的节点也会越近。越远的节点一方面由于经过的网络线路太复杂,往往也就越难以提供高速的数据交换服务,另一方面很有可能在寻找到它之前就已经下载完成了,记录不上,因此DHT在相近的网络环境中才可通用,比如同在一个校园网的多台电脑。

PT下载

混迹BT下载多的网友应该听说过“PT”,它和BT只一字之差,且关系密切,很多人就以为PT是一个特殊的BT,但实际上二者可相去甚远…

  • 先来捋一下基本概念:BT下载指的是BitTorrent,是一个协议,也就是常说的“种子”,而PT指的是Private Tracker,是指的一类私有的Tracker网站[10],更广义一点:指的是一种组织形式。
  • 它的“私有”体现在:
    1. 通常不允许直接注册,而以邀请注册的形式居多。
    2. 相对于BT下载,限制更多,比如通常PT站就对会员的“上传率”,也就是上传的东西和下载的东西有要求,对于上传率不合格的会员则通常直接踢出圈子。
  • 但是这种精英主义的做法也自然而然带来了一些优势:
    1. 由于网站不公开,且会员都是邀请进入,有更大可能性躲过互联网的内容审查,因此更有可能保留一些稀缺资源。
    2. 因为大家都要满足上传率的要求,因此通常上行带宽并不会做限制(甚至有时还希望你下载的快点),对于下载方来说,下载体验会比较优秀。
  • 总的来说,这有点像在游戏中搭私服一样,在对等网络中划了一块小的网络,不与外界交换,只在内部圈地自萌。游戏官方肯定是不希望玩家搭私服的,因为这样会影响官方的收益,但因为我们每次BT下载时实际上跟BitTorrent协议的创始人半毛钱关系没有,所以这个事也就慢慢默许下来了。

下载器盘点

和上一期的RSS一样,P2P下载也已经是“老一辈网民”才熟悉的东西了(我算是最后一批吧),现在大多数人更加熟悉的方式是网盘、在线播放等。

因此我想其实也没多少人会在意这个….还是聊一聊吧

另外需要说明的是,目前eD2k的链接已经非常少了,Magnet占了绝对的主流,大多数人都直接以“磁力下载器”代称P2P下载器了,下文亦同。

迅雷

迅雷迅雷
  • 在国内谈磁力下载,迅雷是一个躲不过去的话题。
  • 一方面,它是最早的一批国产下载器,支持非常多的下载协议,并且很多冷门资源也下的动,而且它自己的云盘也提供了免费磁力离线下载功能,这些都是它的优点。对普通用户来说,它的确是个不错的选择。
  • 但另一方面,很多资源之所以冷门,很大程度上也和迅雷脱不了干系。迅雷有一个别称“吸血雷”,它高度概括了迅雷下载的特点:抓取、不分享。
    • 抓取:例如对于一个Tracker服务器,迅雷会在你本地虚拟出很多机器同时向服务器请求,这样就能以少量CPU性能为代价换取更高的下载速率,但这么做的后果一方面是提高服务器负载,另一方面是降低了其他用户的下载速度。
    • 不分享:常规P2P软件下载时,若有不同机器下载同一文件时,这些机器之间便会建立连接,交换各自的文件。而使用迅雷下载时,它则只从其他机器下载,而不分享自己的文件(或者说只分享给迅雷用户),这样就会导致迅雷用户之间的下载速度很快,但其他用户的下载速度却很慢。
    • 甚至后来,有爆料说迅雷会将磁力下载的资源存在自家服务器上,只有迅雷用户才能下载。其实从这时开始,他就已经不是一个P2P下载器了,这也是为什么它能下的动一些冷门资源。
  • 因此,客观来讲,迅雷是挺好用,但是无疑违背了P2P下载开放、共享的初衷,这也是为什么它在国内的口碑一直不好的原因。

Aria2

Aria2
  • Aria2是一个使用C++编写的开源下载器,它支持多种主流下载协议,全平台(Windows、Linux、MacOS、Android)支持,可定制性高,高性能,并且不带界面,这使得它的可执行文件的体积很小,易于嵌入。
  • 如果你只想要一个简单纯粹的下载器,让Aria2在后台以服务形式运行是个很好的选择。而且Aria2自身的优秀吸引了很多开发者为其做适配,相关的软件生态、脚本和教程都很完善。唯一不太方便的是,Aria2修改设置项几乎全靠手动编辑配置文件,但好在已经有很多人自发地分享配置文件了。
  • Aria2可以通过种子文件和Magnet磁力链接进行P2P下载,但并不支持eD2k协议。不过这并不算什么缺点,本身eD2k协议就已经很少用了。
  • 此外,Aria2同样适合在服务端使用:client使用RPC协议(默认是JSON-RPC)与host上的Aria2通信,这是一种建立在Socket之上的通信协议[8],因此你可以很方便地通过常规的网络编程,调用另一台主机(服务器)上的Aria2服务,实现远程下载。
  • 其他诸多基于Aria2的下载器(例如Motrix)的下载能力与原始的Aria2相同,便不再赘述。

qBitTorrent

qBitTorrentqBitTorrent
  • qBitTorrent是使用C++和Qt编写的开源BitTorrent客户端(注意它和Aria2的不同,它是BitTorrent的开源客户端,并非通用下载器),桌面主流平台(Windows、Linux、MacOS)都支持,可定制性高,同样高性能。
  • qBitTorrent也支持远程调用(默认关闭),但它是提供了一个WebUI以供远程操作,你可以直接在浏览器中操作,更直观一些。
  • qBitTorrent和Aria2在很多方面都相似,不由得让人想比较一下。但实际上两者定位本身就不同,比较结果也就比较娱乐化了,大家不要上纲上线。
项目 Aria2 qBitTorrent
协议支持 Bittorrent, Magnet Bittorrent, Magnet
安装包/压缩包大小 2.36 MB (1.37.0 Windows版本 预编译压缩包) 34.1 MB (4.6.2 Windows版本 安装包)
界面 有 (基于Qt框架)
预设Tracker
远程操作 是,使用RPC协议远程控制 是,提供WebUI界面远程操作
特色功能 RPC远程调用 WebUI远程操作, RSS订阅, DHT管理, 可自定规则

BitComet

BitCometBitComet
  • BitComet(比特彗星)是一个使用C++编写的(闭源)BitTorrent客户端,桌面主流平台(Windows、Linux、MacOS)都支持,可定制性高,高性能。除此之外它还提供了安卓客户端,在安卓平台为数不多的磁力下载器中显得高人一头,毕竟它是一个经历过桌面端验证的,成熟的BitTorrent客户端。
  • BitComet相比于qBitTorrent功能更丰富一些,比如边下边放,就类似于迅雷的“边下边播”。
  • 但是嘛,似乎BitComet并不如qBitTorrent流行。一方面可能是因为它是个闭源软件,而qBitTorrent因为开源获得不少第三方支持;另一方面在我使用时也感到似乎qBitTorrent速度更快些,BitComet在最本职的下载上做的不如qBitTorrent。

ADM

ADMADM
  • ADM(Advanced Download Manager)是一款安卓应用,比较突出的优点是多线程下载和磁力下载。
  • ADM算是安卓上为数不多的选择之一,如果在安卓设备上下载磁力链接,大概只有迅雷、BitComet和ADM了。
  • 但是,单是有贴片广告这一点ADM就已经被其他下载器完爆了,更何况它多线程速度和Chromium多线程下载半斤八两,磁力下载不如BitComet和迅雷,因此我并不推荐使用它。
  • 说起来,似乎安卓的磁力下载器中,不支持Tracker已经成为共识了,迅雷就不说了,BitComet和ADM也都不支持,因此用安卓设备下载磁力大体上是一件十分蛋疼的事情。

参考资料

  1. 超文本传输协议 | 维基百科
  2. 网络蚂蚁 | 维基百科
  3. 种子都没人做了?为什么现在下载器没人用了? | 差评
  4. eDonkey网络 | 维基百科
  5. 为什么网际快车(Flashget)会没落? - 知乎
  6. eD2k链接 | 维基百科
  7. MD4_百度百科
  8. 区别下RPC与HTTP
  9. DHT:点对点网络通信的魔法之源
  10. BT和PT有什么区别? - IMFile.io的回答 - 知乎

延伸阅读