BT是如何下载的
BT协议简介
一、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 (各种浏览器)来完成文件的下载。
对以上两种下载方式做一个简单总结:
Client连接到指定的Server(HTTPServer、FTPServer)下载文件 。
如果用户想要更快的下载速度呢?
一种选择是,Client使用多线程下载,抢占更多的服务器资源(早期的网际快车FlashGet就是这种方式)。
如果用户量很大,这样无疑对Server造成很大的压力。然后呢,Server提供商(网站方)需要提供更多的服务器和更高的带宽,但是这需要花很多钱。
那么,有没有更低成本的解决方案呢?接下来就出现了BT下载。
BT是BitTorrent的缩写,Torrent是激流、洪流的意思,Bit洪流,看名字就很牛的样子。和以上两种下载方式最大的区别就是用户不再直接从服务器下载文件,而是用户之间相互下载,这种方式叫做P2P (Peer to Peer 点对点)。
参与的人越多,下载速度越快
二、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种子)出场了。作为老司机,你那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-8 |
… |
… |
以及其他扩展信息 |
我们找一个种子文件片段来瞧一下:
是不是有似曾相识却又看不懂的感觉呢?这是因为.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 协议的一些细节描述,对细节感兴趣的话可以继续看一下
三、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处理,各个参数的意义如下:
参数名称 |
参数意义 |
info_hash |
torrent文件中info属性的value部分(bencode格式)的SHA1 哈希值,这个哈希值是BT下载任务的唯一标识。 |
peer_id |
任务启动时BT Client为自己随机分配的20字节的ID |
ip |
BTClient的外网IP |
port |
BTClient监听的端口 |
uploaded |
BTClient对该任务已上传的字节数 |
downloaded |
BTClient对该任务已下载的字节数 |
left |
BTClient对该任务尚未下载的字节数 |
event |
可选字段,表示BTClient对当前下载任务的状态,可选值:started,completed,stoped |
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用来判断对端是否仍然存活。
消息类型的取值及作用:
取值 |
名称 |
作用 |
0 |
choke |
发送该消息表示本断发送阻塞,对端将不能获取到piece数据。 |
1 |
unchoke |
发送该消息表示解除阻塞,对端可以开始发送请求获取piece数据。 |
2 |
interested |
发送该消息,表示对对端的pieces数据有兴趣。 |
3 |
not interested |
发送该消息,表示对对端的pieces数据没有兴趣了。 |
4 |
have |
发送该消息,通告对端 本端已完成的pieces,payload为4个字节的piece index |
5 |
bitfield |
发送该消息,通告对端 本端拥有的piecess,通过bitmap的方式表示每个piece index在本端是完成下载。 |
6 |
request |
piece请求消息,payload为: index, begin, and length,都是4个字节表示(网络字节序),length一般实现为0x8000, 最大不能超过0x20000 |
7 |
piece |
piece 数据,Payload为: index, begin,data |
8 |
cancel |
发送该消息,表示本端取消了某个piece请求。payload为:index, begin, and length |
如下是一个request和一个piece消息:
choke, unchoke, interested, not interested消息综合完成Peers的流控策略,以期达到更好的网络吞吐以及维持下载的公平性,一个指导思想是更多的上传将获得更多的下载。
在BTClient的实现过程中还会涉及到很多的程序设计问题,比如:异步socket操作、多线程控制、流量控制、缓存策略、下载优先级、文件存储等,这里就不再一一展开了。
五、告一段落
看了上面的内容以后,对BT下载的原理是否有些了解了呢?关于BT协议的标准及扩展可以到BitTorrent官网(http://www.bittorrent.org/)上获取。。
关于文章的内容或者讲解方式的问题,都欢迎直接和我交流探讨。
后续会不断更新各种互联网常用协议,预计下一篇是HTTP协议的简介。如果你也对互联网协议感兴趣,欢迎关注本人公众号inet-protos 。
BT是如何下载的的更多相关文章
- 西部世界第二季全集高清百度云在线观看BT种子迅雷下载
原名:Westworld地区:美国语言:英语首播:2018-04-23 周一制作公司:HBO类型:科幻/惊悚/悬疑/西部别名:西方极乐园编剧:乔纳森·诺兰 / 丽莎·乔·诺兰导演:乔纳森·诺兰主演:埃 ...
- [搜片神器]直接从DHT网络下载BT种子的方法
DHT抓取程序开源地址:https://github.com/h31h31/H31DHTDEMO 数据处理程序开源地址:https://github.com/h31h31/H31DHTMgr DHT系 ...
- [放松一下] 经典高清电影合集 170G BT种子下载
经典高清电影合集 170G BT种子下载 点击文件名下载 经典高清电影合集170G BT种子.torrent 下载方法 经典高清电影合集详情见目录: 1. 杀手47 2. 这个杀手不太冷 3. 放牛班 ...
- 常用下载方式的区别-BT下载、磁力链接、电驴
出处:https://www.jianshu.com/p/72b7a64e5be1 打开 115 离线下载的窗口,看到支持这么多种链接,你都清楚他们是什么原理嘛?接下来我们一个一个说. 一.HTTP( ...
- BT下载原理分析
版权声明:本文为博主原创文章,未经博主允许不得转载. BitTorrent协议. BT全名为BitTorrent,是一个p2p软件,你在下载download的同时,也在为其他用户提供上传upload, ...
- 【转】扫盲 同步利器、分布式网盘--BT Sync
原文地址:http://program-think.blogspot.com/2015/01/BitTorrent-Sync.html先向大伙儿宣布个好消息——经过多位热心读者的大力支持,经过几天的努 ...
- 扫盲 BT Sync——不仅是同步利器,而且是【分布式】网盘
先向大伙儿宣布个好消息-- 经过多位热心读者的大力支持,经过几天的努力,已经完成了"微软网盘"到"BitTorrent Sync"的迁移工作. 再次向这批热心读 ...
- 33、多线程断点下载的实现&界面的更新
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- 利用迅雷提供的接口从磁力链得到bt种子文件
本地下载工具的磁力链下载速度不给力,而百度云盘有提供离线下载服务,相当于就是直接到服务器取个链接而已.但这需要bt文件,而我只有链力链.网上搜了一下,可以从磁力链构造一个bt文件的下载地址,用pyth ...
随机推荐
- PYTHON单元测试
PYTHON开发入门与实战11-单元测试 1. 单元测试 本章节我们来讲讲django工程中如何实现单元测试,单元测试如何编写以及在可持续项目中单元测试的重要性. 下面是单元测试的定义: 单元测试是开 ...
- [转]JS中的prototype
JS中的phototype是JS中比较难理解的一个部分 本文基于下面几个知识点: 1 原型法设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个 ...
- Mysql sql声明召回2 --正则表达式
这里简单回顾mysql在过滤后的数据使用正则表达式时.主要利用每方法将样品,或添加一些简短的说明. 下面说说提前,使用正则表达式是用来过滤数据 REGEXPkeyword 基本字符相匹配: SELEC ...
- Java8的日期和时间的库20经常使用的演示样本
除了lambda表达,stream以及从一些小的改进,Java 8还推出了新的日期和时间API,在本教程中,我们将展示通过几个简单的任务来学习如何使用示例Java 8这组API.Java至今.日历和时 ...
- .net中用Action等委托向外传递参数
原文:.net中用Action等委托向外传递参数 一般我们可以使用ref,out达到向外传递参数目的. Action<T>是一个特殊的委托,除了常规应用.我们还可以用它来实现简单 ...
- 使用JavaScriptSerializer进行序列化日期类型应该注意的问题
原文:使用JavaScriptSerializer进行序列化日期类型应该注意的问题 JavaScriptSerializer在序列化DateTime时,是用刻度来表示的,具体在Json体现为:\/Da ...
- POI导出Excel文档通用工具方法
import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Map; imp ...
- DataTable相关操作,筛选,取前N条数据,获取指定列数据
DataTable相关操作,筛选,取前N条数据,获取指定列数据2013-03-12 14:50 by Miracle520, 2667 阅读, 0 评论, 收藏, 编辑 1 #region DataT ...
- 从久负盛名的GoDaddy开发革命来看Node.js的风靡程度
英文原文连接:http://venturebeat.com/2015/02/09/godaddy-nodejitsu/ 网站主机托管公司GoDaddy将要进一步通过新的开发工具来提升自身能力.最新消息 ...
- Swift编程语言学习4.1——周期
Swift它提供了类似 C 流量控制结构语言,它包含运行多个任务的能力for和while周期.选择根据不同的编码分支机构的具体条件来运行if和switch声明,有控制流程跳转到其他代码break和co ...