BT协议简介
在互联网上下载文件的方式大概有这么几种:FTP、HTTP、BT、eMule(电驴)等, 阅读器会直接支持FTP和HTTP下载,BT和eMule下载1般需要专用的下载软件的支持。
接下来分别简单介绍1下他们的区分:
FTP 是 File Transfer Protocol(文件传输协议)的英文简称,顾名思义,就是提供文件传输的1个协议。首先需要有1个FTP Server,负责文件的存储并接受网络要求(FTP连接和指令)提供下载,然后FTP Client 向FTP Server发起网络要求,并将接遭到的文件内容保存到本地。
HTTP是HyperText Transfer Protocol (超文本传输协议)的英文简称,超文本就是我们平时所说的网页,通过网页上的链接把众多的网页组织成1个超级大的信息节点网络,所以叫超级文本。文件下载只是HTTP协议所支持的1个子功能,一样需要HTTP Server (Nginx、Apache、IIS等)和 HTTP Client (各种阅读器)来完成文件的下载。
对以上两种下载方式做1个简单总结:
Client连接到指定的Server(HTTPServer、FTPServer)下载文件 。
如果用户想要更快的下载速度呢?
1种选择是,Client使用多线程下载,抢占更多的服务器资源(初期的网际快车FlashGet就是这类方式)。
如果用户量很大,这样无疑对Server造成很大的压力。然后呢,Server提供商(网站方)需要提供更多的服务器和更高的带宽,但是这需要花很多钱。
那末,有无更低本钱的解决方案呢?接下来就出现了BT下载。
BT是BitTorrent的缩写,Torrent是激流、洪流的意思,Bit洪流,看名字就很牛的模样。和以上两种下载方式最大的区分就是用户不再直接从服务器下载文件,而是用户之间相互下载,这类方式叫做P2P (Peer to Peer 点对点)。
参与的人越多,下载速度越快
要做到P2P下载首先需要解决以下两个问题:
1、 如何知道哪些Client在下载同1个文件?
2、 对某1个文件,如何做到同时从多个来源进行下载?
对第1个问题的解决方案:
设计1个TrackerServer(跟踪服务器),每个Client需要去这里上报自己正在下载的文件和自己的ip地址和监听的端口。新来的Client先要连接到TrackerServer,根据要下载的文件查询当前正在下载这个文件的Clients (Peers)。
对第2个问题的解决方法:
Client从TrackerServer获得Peers后,分别向他们发起连接并询问当前的下载进度,然后,同时连接多个Peers分别下载他们已完成的文件片断,最后拼接出完全的文件。
那末对下载进度应当如何表达呢?
由于文件不是被顺序下载的(由于需要从Peers同时下载不同的片断),所以不可以通过当前已完成的字节数来表示进度。
那末,最简单有效的方式就是把文件分割成相同大小的片断(Piece),片断的大小1般是2^n,比如2^18=256K,通过已完成Pieces的序号列表来表示当前的下载进度。
另外,由于Pieces序号是连续的,可以通过BitMap的方式表示每一个Piece Index是不是已完成。Piece Index所在的bit位为1,表示该Piece已下载完成。
如果下载任务是1个文件夹(包括很多文件), 可以把这些文件依照固定的顺序连接起来(逻辑上)进行Pieces切分。
当Client获得到Peers的完成列表后,就能够将不同的Pieces分配到对应的Peers进行并行下载,同时将自己已完成的Pieces提供给其他Peers来下载。
互帮互助、互通有没有的和谐社会就此开启了。
到目前为止,我们还有几个关键问题没有解决:
1、怎样找到待下载文件的TrackerServer?
2、Peers对文件分片的规则是不是1致?
3、在TrackerServer上怎样唯1的标识1个下载任务?
4、下载来的Pieces是不是在传输进程中出现了毛病或被歹意篡改?
为了解释上面的问题,此处应当有.torrent文件(BT种子)出场了。作为老司机,你那30G的种子有无鉴赏过里面都是甚么数据呢?
BT种子文件主要包括以下关键信息:
名字 |
类型 |
意义 |
announce |
String |
TrackerServer的地址 |
announce-list |
List of list |
TrackerServer分组列表 |
info |
Dict (kv集合) |
包括了待下载文件的基本信息:
如文件名称、目录名称、分片大小、分片SHA1哈希值等。 |
publisher |
String |
种子发布者名称 |
publisher-url |
String |
种子发布者URL |
nodes |
List |
DHT(散布式哈希表)的节点列表, 咋就 DHT Protocol中定义, 类似于eMule的Kad网络,实现了Trackerless。 |
encoding |
String |
种子文件的字符编码,如 UTF⑻ |
… |
… |
和其他扩大信息 |
我们找1个种子文件片断来瞧1下:
是否是有似曾相识却又看不懂的感觉呢?这是由于.torrent文件是bencoding编码表示的。
bencoding编码是1种对象序列化表示法(功能和json是1样的,但是规则不1样),bencoding 编码通过开头的字符来指定接下来的对象的类型,规则以下:
'd'开头表示是dict类型,可以理解为key=>value的集合,'e'表示结束
'l'(小写字母L)开头表示是list类型,'e'表示结束
'i' 开头表示是integer类型,'e'表示结束,可以表示负数
数字 开头表示string类型,数字为string的长度,长度与string内容以':'分割开
上图中标注的地方8:encoding5:UTF⑻4:infod5:files,依照这个规则解析后得到
encoding=>UTF⑻
info => { files=> …}
至此,总结1下BT下载的基本进程, 聪明的你是不是已了解BT下载了呢?
---------------------------------------------------------我是分割线---------------------------------------------------------------
接下来是对BT 协议的1些细节描写,对细节感兴趣的话可以继续看1下
TrackerServer有HTTP和UDP协议两种,这里简单介绍1下HTTP协议的TrackerServer,BTClient通过 HTTP Get要求完成Peers获得和本身的注册。要求的URL格式以下:
Trackerserver-url?info_hash=xxxxxxxxxxxx,peer_id=xxxxxxxxxxx,ip=x.x.x.x,port=xxxx,uploaded=xx,downloaded=xx,left=xx,event=x
URL中各参数需要经过urlencode处理,各个参数的意义以下:
参数名称 |
参数意义 |
info_hash |
torrent文件中info属性的value部份(bencode格式)的SHA1 哈希值,这个哈希值是BT下载任务的唯1标识。 |
peer_id |
任务启动时BT Client为自己随机分配的20字节的ID |