- 简述
BT下载是采用P2P的下载方式,下载的大致形式采用如下图所示,处于图示中心的称为Tracker服务器,其余称为Peer。
缺点
1.资源的安全性
2.资源的实效性(没有上传者则BT也将失效)
3.版权
- 协议分析
对BT协议(1.0)的分析主要包含4个部分:
1.种子文件的分析
2.同Tracker服务器的通讯(采用HTTP协议)
3.同其他peer(配合/协同者)的通讯(采用TCP协议)
4.总结
分析前的了解
在这些分析之前,需要先了解两点BT协议采用的基础:
1.BT协议中采用的单位
2.BT协议中采用的编码
1--单位说明:
下载的文件被划分成大小相同的piece(除了最后一个),以1 – 256KB (假设一个piece=256KB)称为第1个piece,之后按顺序称呼,每个piece都有独特的hash值,作为版本号。
piece下面又划分了block,block一般为固定值16KB,在同peer(同为下载者的对象主机)之间每次传输的单位为block,client(本机)需要记录该block的是属于那个piece的block。
Tips:
1.piece需要是16KB的整数倍
2.对piece的校验流程:
下载完成 è 使用标准算法(Sha1)计算1的hash值 è 比较种子文件的hash值同2的hash值
2--单位说明:
种子文件又成metafile(元文件),文件内部的编码采用BenCode(B编码),BenCode中存在4中类型。
类型 |
格式及范例 |
字符串 |
格式:<字符串长度>:<字符串> 范例:字符串good 4:good |
整型 |
格式:i<十进制的整型数>e => i(interge)为起始符,e(end)为结束符 范例:数字5 i5e |
列表 |
格式:l<其他类型>e =>l(list)为起始符,e(end)为结束符 范例:字符串good + 字符串nihao l4:good5:nihaoe |
字典 |
格式:d<关键字><值>e =>d(dictionary)为起始符,e(end) 其中:关键字必须为字符串,值则未限定 范例:good为key,列表nihao和hello为值 d4:goodl5:nihao5:helloee |
协议分析(1)--种子文件分析
(a)枚举文件说明
=>以文本打开单文件.torrent文件:
d8:announce35:http://192.168.73.197:8080/announce10:created by13:BitComet/1.3713:creation datei1472779924e8:encoding5:UTF-84:infod4:ed2k16:??~_x0010_€?_x001D_8_x0007_/vG8:filehash20:E氙率>w?⒂?y<?伖6:lengthi30791e4:name22:btdownloadservice.mmap10:name.utf-822:btdownloadservice.mmap12:piece lengthi32768e6:pieces20:E氙率>w?⒂?y<?伖e5:nodesll4:6881i0eel5:37049i0eel5:33281i0eel5:18021i0eel5:51413i0eel5:21793i0eel5:51413i0eel5:18672i0eel4:6881i0eel4:5712i0eee9:publisher10:hejianglin15:publisher.utf-810:hejiangline
解析情况
=>以文本打开多文件.torrent文件:
d8:announce35:http://192.168.73.197:8080/announce10:created by13:BitComet/1.3713:creation datei1472781603e8:encoding5:UTF-84:infod5:filesld4:ed2k16:鳛 *羉_x0007_実?⒚!彐o8:filehash20:碊?a?戎7暰毿警U_x0019_6?:lengthi5e4:pathl9:test1.txte10:path.utf-8l9:test1.txteed6:lengthi32763e4:pathl104:_____padding_file_0_濡傛灉鎮ㄧ湅鍒版鏂囦欢锛岃鍗囩骇鍒癇itComet(姣旂壒褰楁槦)0.85鎴栦互涓婄増鏈琠___e10:path.utf-8l104:_____padding_file_0_濡傛灉鎮ㄧ湅鍒版鏂囦欢锛岃鍗囩骇鍒癇itComet(姣旂壒褰楁槦)0.85鎴栦互涓婄増鏈琠___eed4:ed2k16:?c]獝狎褧Ao顫?:filehash20:_x0010_烱<P装遰?浧飷f?6:lengthi5e4:pathl9:test2.txte10:path.utf-8l9:test2.txteee4:name3:dir10:name.utf-83:dir12:piece lengthi32768e6:pieces40:B橫?鬝笫Pi烃}璭鑱k_x0010_烱<P装遰?浧飷f?e5:nodesll4:6881i0eel5:37049i0eel5:33281i0eel5:18021i0eel5:51413i0eel5:21793i0eel5:56963i0eel5:38322i0eel5:26121i0eel4:5712i0eee9:publisher10:xxxxxxxxxx15:publisher.utf-810:xxxxxxxxxxe
解析情况
关于各个关键key的作用请看下面(b)key的说明
(b)key说明
=>单/多文件都包含的key说明
key |
说明 |
announce |
Tracker的主服务器 |
announce-list(可选) |
Tracker服务器备用列表 |
creation date(可选) |
种子文件建立的时间 |
comment(可选): |
种子文件的注释 |
created by(可选) |
创建人或创建程序的信息 |
info |
文件信息,二种情况:单文件结构或多文件结构 |
=>单文件中的info说明
key |
说明 |
length |
文件的大小,用byte计算 |
md5sum(可选) |
MD5校验和,不使用 |
name |
文件名 |
piece length |
每个piece的大小,用byte计算 |
pieces |
每个piece的20个字节的SHAT Hash的值 |
=>多文件中的info说明
key |
说明 |
files |
表示文件的名字和大小下面说明 |
md5sum(可选) |
MD5校验和,不使用 |
name |
目录名字 |
piece length |
每个piece的大小,用byte计算 |
pieces |
每个piece的20个字节的SHAT Hash的值 |
=>多文件中的files说明
key |
说明 |
lenghth |
文件的大小,用byte计算 |
path |
文件的名字 |
path.utf-8 |
文件名的UTF-8编码 |
有点乱,请看(c)总结
(c)总结
=>单文件torrent的种子结构信息
├─announce
├─announce-list
├─comment
├─comment.utf-8
├─creation date
├─encoding
├─info
│ ├─length
│ ├─name
│ ├─name.utf-8
│ ├─piece length
│ ├─pieces
│ ├─publisher
│ ├─publisher-url
│ ├─publisher-url.utf-8
│ └─publisher.utf-8
└─nodes //dht
=>多文件torrent的种子结构信息
├─announce
├─announce-list
├─comment
├─comment.utf-8
├─creation date
├─encoding
├─info
│ ├─files
│ │ ├─length
│ │ ├─path
│ │ └─path.utf-8
│ ├─name
│ ├─name.utf-8
│ ├─piece length
│ ├─pieces
│ ├─publisher
│ ├─publisher-url
│ ├─publisher-url.utf-8
│ └─publisher.utf-8
└─nodes //dht
BT协议分析(2)--同Tracker服务器的通讯(采用HTTP协议GET方式)
(a)目的
1.将下载进度报告给Tracker以便Tracker进行相关统计
2.获取当前下载同一个资源的peer的IP和端口号
(b)操作
=>主机发送给Tracker服务器请求当前连接着同一文件的peer地址
格式:<Tracker服务器地址>?<parm1=value1>&<><parm2=value2>...
例如:
http://tk.greedland.net/announce?
info_hash=01234567890123456789
&peer_id=01234567890123456789
&port=3210
&compact=1
&uploaded=0
&downloaded=0
&left=8000000
&event=started
参数说明:
参数 |
意义 |
info_hash |
种子文件info对应的hash值(固定20字节) |
peer_id |
随机标识符,表示自身的请求(固定20字节) |
port |
主机监听端口号,用与同其他peer的连接请求 |
uploaded |
当前的上传总量(单位Byte) |
downloaded |
当前的下载总量(单位Byte) |
left |
剩余下载量,即下载总量 - 已下载量 |
compact |
Tracker服务器的反馈当前peer的方式 1 = 每个peer占6个字节,前4字节为peer的IP地址,其余为peer的端口号 |
event |
主机的下载状态: start = 主机开始下载(主机同Tracker首次通信时) completed = 主机已完成下载 stoped = 结束,主机即将关闭 |
ip |
可选,主机IP地址 |
numwant |
可选,Tracker服务器反馈peer的数量(默认50个) |
key |
可选,随机标识符 |
trackerid |
可选 |
=>Tracker服务器返回结果(B编码的字典)
d //
8:complete //..已完成数量
i100e
10:incomplete // ..未完成数量
i200e
8:interval // ..间隔时间
i1800e
5:peers // ..当前peers
300:......
e
参数说明:
关键字 |
意义 |
failure reason |
GET失败的原因(human string) |
warning message |
GET警告字符串(human string) |
interval |
主机下次连接Tracker所需时间(单位:秒) |
min interval |
主机下次连接Tracker所需的最小时间(单位:秒) |
tracked id |
指明Tracker的ID |
complete |
整数,当前存在多少个peer已完成该文件的下载 |
incomplete |
整数,当前存在多少个peer未完成该文件的下载 |
peers |
各个peer的IP和端口号,字符串 |
具体分析:
URL的具体情况:/announce?info_hash=%98%13%c7%a0%87%eb%a7%a6gh%dc%86kU%03m%ff%2fr%94&peer_id=-UT348B-%03%a6%df%91%063%f8%daC%1e%02F&port=24842&uploaded=0&downloaded=0&left=13547779828&corrupt=0&key=917599C2&numwant=200&compact=1&no_peer_id=1 HTTP/1.1
回包信息:
BT协议分析(3)--同其他peer(配合/协同者)的通讯(采用TCP协议)
(a)通讯协议格式说明
主机同peer之间的通讯格式主要分为两种:握手及其他
=>握手采用的格式和参数说明
格式:<pstrlen><pstr><reserved><info_hash><peer_id> |
||
参数 |
所占字节数 |
意义 |
pstrlen |
1 |
pstr的长度,为固定值19 |
pstr |
19 |
BitTorrent protocol,BitTorrent协议的关键字 |
reserved |
8 |
扩展字节,一般设置为0 |
info_hash |
20 |
同主机发送到Tracker的Get请求中的info_hash为同值 |
peer_id |
20 |
识别BT软件类型 |
=>其他的参数说明
格式:<length prefix><message ID><payload> |
||
参数 |
所占字节数 |
意义 |
length prefix |
4 |
表示message ID 和 payload的长度和 |
message ID |
1 |
十进制整数,表示消息的编号 |
payload |
随机 |
负载,表示消息的内容 |
message ID说明
消息类型 |
消息格式 |
所占字节数 |
意义 |
keep_alive |
<len=0000> 即:0000 |
4 |
2分钟内没有向peer发送任何消息,则发送此消息 |
choke |
<len=0001><id=0> 即:00010 |
5 |
阻塞接收消息的peer,即该peer无法下载主机资源 |
unchoke |
<len=0001><id=1> 即:00011 |
5 |
解除阻塞。
|
interested |
<len=0001><id=2> 即:00012 |
5 |
通知peer,peer上存在主机上没有的资源 |
not interested |
<len=0001><id=3> 即:00013 |
5 |
通知peer,peer上存在的资源主机上都有 |
have |
<len=0005><id=4><piece index> 即:00054<piece index> |
9 |
通知所有peer,主机拥有此index的piece |
bitfield |
<len=0001 + X(见注1)><id=5><bitfield> 即:< 1(表示id长度) +bitfile的长度>5<bitfield> |
不固定 |
主机同peer端交换当前资源的信息 |
request |
<len=0013><id=6><index><begin><length> 即:000136<piece的索引><piece的偏移><请求的数据长度> |
17 |
主机请求获取peer上的资源 |
piece |
<len=0009+X><id=7><index><begin><block> 即:<9+block的长度(见注2)>7<index><begin><block> |
不固定 |
主机上传资源到peer上 |
cancel |
<len=0013><id=8><index><begin><length>即: 000138<piece的索引><piece的偏移><请求的数据长度> |
17 |
同request的作用相反,用于取消获取的请求 |
port |
<len=0003><id=9><listen-port> 即:00039<监听端口> |
7 |
只在支持DHT(见注3)的主机上使用,指明DHT监听的端口号 |
注1:
X:表示为(Bit)位图的长度,每个Bit代表一个Piece,假设当前文件为801个piece,则需要801个Bit来表示,也即101个字节,第一个Bit表示第一个piece,Bit为1表明当前主机拥有此piece。
注2:
9 = id(1) + index(4) + begin(4)
X表示block的长度
block表示传输的资源数据(一般为slice的长度)
注3:
DHT:Distributed Hash Table(分布式哈希表),每个客户端都可以充当服务器,这样在没有Tarcker服务器的时候,主机仍然可以在其他peer上下载文件。采用UDP协议(采用的端口号同TCP端口号一致)
完全不知道是什么?请看(b)交互步骤
(b)交互步骤
步骤1.建立握手消息,创建针对peer的状态变量
当前主机对成功建立连接peer都需要维护一个和peer之间的状态信息
状态变量 |
意义 |
am_chocking |
意义:主机阻塞标志 1 = 主机同peer信息阻塞,peer不可以获取主机数据 0 = 非阻塞,peer可以获取主机数据 default = 1 |
am_interested |
意义:主机数据不完整标志 1 = peer存在主机没有的piece 0 = peer上的piece主机上都有 default = 0 |
peer_chocking |
意义:peer阻塞标志 1 = peer同当前主机阻塞,主机不可获取peer端数据 0 = 非阻塞,主机可以获取peer数据 default = 1 |
peer_interested |
意义:peer数据不完整标志 1 = 主机存在peer没有的piece(数据) 0 = 主机上的piece,peer上都有 default = 0 |
步骤2.互换所拥有的资源情况
采用上述的bitfield交换数据
步骤3.交流对资源的意愿信息
采用上述的choke/unchoke/interested/not interested /have 交换数据
步骤4.互相请求资源
采用上述的request / cancel / piece交换数据
步骤5.断开连接
(c)交互算法
下载策略:
1.片段选择法
a)向一个peer请求完整的一个piece
b)优先请求当前piece拥有者最少的piece
c)在最开始采用随机下载piece
d)但下载中遇上某个piece传输速度慢的情况,客户端向所有的piece发送该piece的block的请求
片段选择策略:
在开始和最后的阶段,随机的去多个peer上获取相同的block
2.阻塞算法
性能优化策略。
每个客户端同固定数量的peer保持疏通,如何判断保持疏通的对象? (根据与peer的连接速度)
BT协议采用每10秒计算与当前peer的连接速度,选取速度最快的4个选择疏通.
另外在处理空闲连接是否具有更好的下载速度时,BT协议为每个peer设定一个optimistic unchoking peer,
每个主机每隔30s计算当前主机同该peer的传输速度,优于最优的那个则采用为4个选择疏通对象的其中一个。
且每隔30s置换一个peer对象.
当主机下载结束后,是如何选择4个疏通对象的?于传输速度最优的4个peer保持疏通关系
- 总结
以图为例,BT采取的流程大致如下。
- 参考
http://www.cnblogs.com/happyhotty/articles/2064058.html
http://www.cnblogs.com/DxSoft/archive/2012/02/11/2346314.html
http://blog.chinaunix.net/uid-26548237-id-3056731.html