发布于 

Go手写BT下载器

每天在B站找灵感的我有发现了一个比较好玩的东西。最近俄罗斯放出了盗版网站,但是大部分都是BT种子,而在中国一般都是用迅雷之类的垃圾软件,限速实在是恶心。而我也想了解一下BT下载的工作原理,于是叔叔就给我推送了一个用go写BT种子的视频。而视频内容只是看了一遍容易忘记,所以这个也是我的学习笔记,若有有关原理的内容则会在下方更新。

中心下载

中心下载是我们平时最长用的方法,我们用户直接在对方服务器中获取我们需要的资源。但是这种下载有一个弊端,就是下载容易受到服务器带宽大小影响。用户在下载时是共用着服务器的出口带宽,用户数一多很容易导致出口带宽被占满,导致用户下载速度慢,对此我们P2P下载对此就有一种解决方案。

P2P下载

P2P下载全程是Peer to Peer,也就是用户对用户下载了。每个下载者在下载时会先到服务器(tracker)上寻找那些下载者的计算机中存放着我们要下载的资源,获取到时我们就对资源进行分片,再在多个较近的下载者电脑中获取资源。就如下图所示,peer4若要下一个资源,首先他会去Server中获取哪些peer拥有这个资源。获取到后我们会去对需要下载的文件分片,比如分为1,2,3这3个片。我们会再去寻找哪个peer中拥有1,哪个peer拥有2,分别下载。下载完成后将3片拼接为一片。为了我们能够确认下载的文件是否被修改,文件的每个片都会生成一个SHA-1加密的密钥进行文件完整性验证。

Torrent File格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
单文件格式:
announce (String): tracker url
announce list ([]String): 备用trackerd的列表
info (dict):文件具体信息。
name (string):文件名称
length (int): 文件总长度。
pieces ([][20]byte): 每个文件片的SHA-1值。
pieces length(int): 每个文件片的长度。

多文件格式(相比单文件格式在info中增加了以下几段):
files([]dict):
path: 文件路径
length:文件长度
...
path: 文件路径
length:文件长度

而我们的TorrentFile的序列化协议是使用Bencode。

Bencode语法

四种格式

  • String:

    • len ‘:’ data
  • int

    • ‘i’ num ‘e’
  • list

    • ‘l’ 元素 元素 ‘e’
  • dict

    • ‘d’ k1 v1 k2 v2 ‘e’

例子如下: