ITPub博客

首页 > 应用开发 > IT综合 > 常见下载方式之BT下载实现过程详解

常见下载方式之BT下载实现过程详解

IT综合 作者:dianliang01 时间:2018-11-28 12:03:09 0 删除 编辑


一、 BT 下载是怎么来的?

在互联网上下载文件的方式大概有这么几种: FTP 、 HTTP 、 BT 、 eMule( 电驴 ) 等, 浏览器会直接支持 FTP 和 HTTP 下载, BT 和 eMule 下载一般需要专用的下载软件的支持。


接下来分别简单介绍一下它们的区别:


FTP  是 File Transfer Protocol (文件传输协议)的英文简称,顾名思义,就是提供文件传输的一个协议。首先需要有一个 FTP Server ,负责文件的存储并接受网络请求( FTP 连接和指令)提供下载,然后 FTP Client 向 FTP Server 发起网络请求,并将接受到的文件内容保存到本地。


HTTP 是 HyperText Transfer Protocol (超文本传输协议)的英文简称,超文本就是我们平时所说的网页,通过网页上的链接把众多的网页组织成一个超级大的信息节点网络,所以叫超级文本。文件下载只是 HTTP 协议所支持的一个子功能,同样需要 HTTP Server ( Nginx 、 Apache 、 IIS 等)和 HTTP Client (各种浏览器)来完成文件的下载。

对以上两种下载方式做一个简单总结:

HTTP 下载 1

 

如果用户想要更快的下载速度呢?


一种选择是, Client 使用多线程下载,抢占更多的服务器资源(早期的网际快车 FlashGet 就是这种方式)。

如果用户量很大,这样无疑对 Server 造成很大的压力。然后呢, Server 提供商(网站方)需要提供更多的服务器和更高的带宽,但是这需要花很多钱。

 

那么,有没有更低成本的解决方案呢?接下来就出现了 BT 下载。


 BT 是 BitTorrent 的缩写, Torrent 是激流、洪流的意思, Bit 洪流,看名字就很牛的样子。和以上两种下载方式最大的区别就是用户不再直接从服务器下载文件,而是用户之间相互下载,这种方式叫做 P2P ( Peer to Peer 点对点)。从下图我们可以看出参与的人越多,下载速度越快


P2P 下载 1

 

二、 BitTorrent 的 P2P 下载是怎么做到的?

 

要做到 P2P 下载首先需要解决如下两个问题:

 

     1 、   如何知道哪些 Client 在下载同一个文件?

 

     2 、   对某一个文件,如何做到同时从多个来源进行下载?

 

对于第一个问题的解决方案:


  设计一个 TrackerServer (跟踪服务器),每一个 Client 需要去这里上报自己正在下载的文件以及自己的 ip 地址和监听的端


口。新来的 Client 先要连接到 TrackerServer ,根据要下载的文件查询当前正在下载这个文件的 Clients (Peers) 。


对于第二个问题的解决方法:


  Client 从 TrackerServer 获取 Peers 后,分别向他们发起连接并询问当前的下载进度,然后,同时连接多个 Peers 分别下载他


们已完成的文件片段,最后拼接出完整的文件。

 

那么对于下载进度应该如何表达呢?


  因为文件不是被顺序下载的 ( 因为需要从 Peers 同时下载不同的片段 ) ,所以不可以通过当前已完成的字节数来表示进度。那


么,最简单有效的方式就是把文件分割成相同大小的片段 (Piece) ,片段的大小一般是 2^n ,比如 2^18=256K ,通过已完


成 Pieces 的序号列表来表示当前的下载进度。



  另外,因为 Pieces 序号是连续的,可以通过 BitMap 的方式表示每个 Piece Index 是否已完成。 Piece Index 所在的 bit 位为 1 ,


表示该 Piece 已经下载完成。



  如果下载任务是一个文件夹 ( 包含很多文件 ) , 可以把这些文件按照固定的顺序连接起来 ( 逻辑上 ) 进行 Pieces 切分。


当 Client 获取到 Peers 的完成列表后,就可以将不同的 Pieces 分配到对应的 Peers 进行并行下载,同时将自己已完成的 Pieces


提供给其他 Peers 来下载。

 

互帮互助、互通有无的和谐社会就此开启了。

 

到目前为止,我们还有几个关键问题没有解决:

 

1 、怎么找到待下载文件的 TrackerServer ?


2 、 Peers 对文件分片的规则是否一致?


3 、在 TrackerServer 上怎么唯一的标识一个下载任务?


4 、下载来的 Pieces 是否在传输过程中出现了错误或者被恶意篡改?


为了解释上面的问题,此处应该有 .torrent 文件 (BT 种子 ) 出场了。


 BT 种子文件主要包括如下关键信息:

BT 种子文件主要信息 1

我们找一个种子文件片段来瞧一下:


 

是不是有似曾相识却又看不懂的感觉呢?这是因为 .torrent 文件是 bencoding 编码表示的。


bencoding 编码是一种对象序列化表示法(功能和 json 是一样的,但是规则不一样), bencoding 编码通过开头的字符来指定


接下来的对象的类型,规则如下:


'd' 开头表示是 dict 类型 , 可以理解为 key=>value 的集合, 'e' 表示结束

'l' (小写字母 L )开头表示是 list 类型, 'e' 表示结束

'i'   开头表示是 integer 类型, 'e' 表示结束,可以表示负数

数字 开头表示 string 类型,数字为 string 的长度,长度与 string 内容以 ':' 分割开

上图中标注的地方 8:encoding5:UTF-84:infod5:files ,按照这个规则解析后得到

encoding=>UTF-8

info => { files=> …}


至此,总结一下 BT 下载的基本过程 , 聪明的你是否已经了解 BT 下载了呢?


BT 种子下载过程 1

 

接下来是对 BT 协议的一些细节描述,对细节感兴趣的话可以继续看一下

 

三、 BT 协议之连接 TrackerServer

 

TrackerServer 有 HTTP 和 UDP 协议两种,这里简单介绍一下 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 处理,各个参数的意义如下:



TrackerServer 的返回内容为经过 bencode 的 Dict 类型,如果返回失败,会包含 "failure reason" 键值,内容为可读的失败原因。

"interval":   为向 Trackerserver 发起常规查询的间隔时间, BTClient 需要按照这个间隔时间定期向 TrackerServer 报告下载状态,同时获取最新的 Peers 信息。

"peers"  : 为一个 Peer List ,每个 Peer 包含以下几项内容:

"peer id" :   为 20 字节的 Peer 自分配 ID

"ip"  : Peer IP 地址

"port" : Peer 监听的端口

抓包得到的一个 TrackerServer 的返回内容 , 经过 bencode 解析后如下:

{ interval =>1800

 

  peers => [

 

         {

 

ip => 100.197.121.204,

 

peer id => -SD0100-\310\225\2576z\264U\240O\034

 

              port => 14678

 

         }

 

   … // 其他 Peer

 

]

 

}

 

      关于 peers 列表,当前大多数 TrackerServer 支持 compact peers 格式以减少返回内容的长度,该格式下 peers 属性为一个 String ,每六个字节为一组,每组表示一个 Peer ,其中前 4 个字节 表示 PeerIP ,后两个字节表示 Peer Port 。  

四、 BT 协议细节之连接 Peers

与 Peer 建立 TCP 连接后,首先发送 HandShake 消息进行协议基本信息的交换,协商成功后,紧接着开始送各自的 PiecesBitmap ( bitfield 消息)。然后向对端发送自己缺失的 Pieces 请求( request 消息),开启 Pieces 交换下载。

 

Handshake 消息主要是协商协议名称、 Info Hash 和 PeerID ,保证对端是相兼容的 Peer ,如果信息协商不上 ( 比如协议名称不是 BitTorrent Protocol , 或者 Info Hash 不一致 ), TCP 连接将被关闭。 HandShake 消息格式如下:

 

 

HashShake 成功之后就开始通过如下一系列 peer_msg 消息来完成下载控制, peer_msg 消息格式如下:



msg_len ( 4 字节)

msg_type ( 1 字节)

payload (若干字节)

如果 msg_len = 0 , 这表示 KeepAlive 消息, KeepAlive 用来判断对端是否仍然存活。

 

消息类型的取值及作用:


 

如下是一个 request 和一个 piece 消息:

choke, unchoke, interested, not interested 消息综合完成 Peers 的流控策略,以期达到更好的网络吞吐以及维持下载的公平性,一个指导思想是更多的上传将获得更多的下载。

 

在 BTClient 的实现过程中还会涉及到很多的程序设计问题,比如:异步 socket 操作、多线程控制、流量控制、缓存策略、下载优先级、文件存储等,这里就不再一一展开了。

 

注:本文由点量软件整理自互联网DolitQin520(V)


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31439365/viewspace-2221935/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
寻找属于自己的玫瑰,也想做哪只被驯养的小狐狸。 点量软件致力于IPTV系统开发、视频加密、实时云渲染串流、APP定制开发+V:DolitQin520

注册时间:2017-02-28

  • 博文量
    126
  • 访问量
    100192