BT协议分析

BitTorrent协议分析一


2.1  概要介绍

BitTorrent(简称BT)是一个文件分发协议,每个下载者在下载的同时不断向其他下载者上传已下载的数据。而在FTPHTTP协议中,每个下载者从FTPHTTP服务器处下载自己所需要的文件,各个下载者之间没有交互。当非常多的用户同时访问和下载服务器上的文件时,由于FTP服务器的处理能力和带宽的限制,下载速度会急剧下降,有的用户根本访问不了服务器。BT协议与FTP协议不同,它的特点是下载的人越多下载的速度越快,其原因在于每个下载者将已下载的数据提供给其他下载者下载,它充分利用了用户的上载带宽。BT协议通过一定的策略保证上传的速度越快,下载的速度也越快。

2.2  基于BT协议的文件分发系统的构成

基于BT协议的文件分发系统由以下几个实体构成。

1)一个Web服务器。

2)一个种子文件。

3)一个Tracker服务器。

4)一个原始文件提供者。

5)一个网络浏览器。

6)一个或多个下载者。

Web服务器上保存着种子文件,下载者使用网络浏览器(如IE浏览器)从Web服务器上下载种子文件。种子文件,又称为元原文件或metafile,它保存了共享文件的一些信息,如共享文件的文件名、文件大小、Tracker服务器的地址。种子文件通常很小,一般大小为1GB的共享文件,其种子文件不足100KB,种子文件以.torrent为后缀。Tracker服务器保存着当前下载某共享文件的所有下载者的IP和端口。原始文件提供者提供完整的共享文件供其他下载者下载,它也被称为种子,种子文件就是提供者使用BT客户端生成的。每个下载者通过运行BT客户端软件下载共享文件。我们把某个下载者本身称为客户端,把其他下载者称为peer

BT客户端下载一个共享文件的过程是:客户端首先解析种子文件,获取待下载的共享文件的一些信息,其中包括Tracker服务器的地址。然后客户端连接Tracker获取当前下载该文件的所有下载者的IP和端口。之后客户端根据IP和端口连接其他下载者,从它们那里下载文件,同时把自己已下载的部分提供给其他下载者下载。

共享文件在逻辑上被划分为大小相同的块,称为piece,每个piece的大小通常为256KB。对于共享文件,文件的第1字节到第256K(即262144)字节为第一个piece,第256K1字节到第512K字节为第二个piece,依此类推。种子文件中包含有每个piecehash值。BT协议规定使用Sha1算法对每个piece生成20字节的hash值,作为每个piece的指纹。每当客户端下载完一个piece时,即对该peice使用Sha1算法计算其hash值,并与种子文件中保存的该peicehash值进行比较,如果一致即表明下载了一个完整而正确的piece。一旦某个piece被下载,该piece即提供给其他peer下载。在实际上传和下载中,每个piece又被划分为大小相同的slice,每个slice的大小固定为16KB16384字节)。peer之间每次传输以slice为单位。

从以上描述可以得知,待开发的BT软件(即BT客户端)主要包含以下几个功能:解析种子文件获取待下载的文件的一些信息,连接Tracker获取peerIP和端口,连接peer进行数据上传和下载、对要发布的提供共享文件制作和生成种子文件。种子文件和Tracker的返回信息都以一种简单而高效的编码方式进行编码,称为B编码。客户端与Tracker交换信息基于HTTP协议,Tracker本身作为一个Web服务器存在。客户端与其他peer采用面向连接的可靠传输协议TCP进行通信。下面将进一步作详细的介绍。


2.3  B编码

种子文件和Tracker的返回信息都是经过B编码的。要解析和处理种子文件以及Tracker的返回信息,首先要熟悉B编码的规则。B编码中有4种类型:字符串、整型、列表、字典。

字符串的编码格式为:<字符串的长度>:<字符串>,其中<>括号中的内容为必需。例如,有一个字符串spam,则经过B编码后为4:spam

整型的编码格式为:i<十进制的整型数>e,即B编码中的整数以i作为起始符,以e作为终结符,iinteger的第一个字母,eend的第一个字母。例如,整数3,经过B编码后为i3e,整数−3B编码为i−3e,整数0B编码为i0e

注意i03e不是合法的B编码,因为03不是十进制整数,而是八进制整数。

列表的编码格式为:l<任何合法的类型>e,列表以l为起始符,以e为终结符,中间可以为任何合法的经过B编码的类型,llist的第一个字母。例如,列表l4:spam4:eggse表示两个字符串,一个是spam,一个是eggs

字典的编码格式为:d<关键字><>e,字典以d为起始符,以e为终结符,关键字是一个经过B编码的字符串,值可以是任何合法的B编码类型,在de之间可以出现多个关键字和值对,ddictionary的第一个字母。例如,d4:spaml3:aaa3:bbbee,它是一个字典,该字典的关键字是spam,值是一个列表(以l开始,以e结束),列表中有两个字符串aaabbb

又如:d9:publisher3:bob17:publisher-webpage15:www.example.come,它也是一个字典,第一个关键字是publisher,对应的值为bob,第二个关键字是publisher-webpage,对应的值是www.example.com

2.4  种子文件的结构

种子文件包含了提供共享的文件的一些信息,它以.torrent为后缀名,种子文件也被称为元信息文件或metafile,它是经过B编码的。种子文件事实上就是一个B编码的字典,它含有以下关键字如表13-1所示。

13-1                                                       种子文件的关键字

    

    

info

该关键字对应的值是一个字典,它有两种模式,“singel file”和“multiple file”,文件模式和多文件模式。单文件模式是指待共享的文件只有一个,多文件模式是指提供共享的不止一个文件,而是两个或两个以上。如使用BT软件下载一部影片时,影片的上下部可能分别放在不同的文件里

announce

该关键字的值为TrackerURL

announcelist

可选,它的值存放的是备用TrackerURL

creationdate

可选,该关键字对应的值存放的是创建种子文件的时间

comment

可选,它的值存放的是种子文件制作者的备注信息,对于下载来说,该关键字基本没有用处,因此不必理会

created by

可选,该关键字对应的值存放的是生成种子文件的BT客户端软件的信息,如客户端名、版本号等,一般不必理会

 

info是最重要的一个关键字,它的值是一个字典,下面对它再作进一步的介绍。无论是单文件模式还是多文件模式,该字典都包含关键字如表13-2所示。

13-2                                                       info包含的关键字

    

    

 

l       piece length

每个piece的长度,它的值是一个B编码的整型,该值通常为i262144e,即256K,也有可能为512K128K

 

l       pieces

对应的值为一个字符串,它存放的是各个piecehash值,这个字符串的长度一定是20的倍数,因为每个piecehash值的长度为20字节

 

l       private

该值如果为1,则表明客户端必须通过连接Tracker来获取其他下载者,即peerIP地址和端口号;如果为0,则表明客户端还可以通过其他方式来获取peerIP地址和端口号,如DHT方式。DHT即分布式哈希表(Distribute Hash Tabel),它是一种以分布式的方式来获取peer的方法,现在许多BT客户端既支持通过连接Tracker来获取peer,也支持通过DHT来获取peer。如果种子文件中没有private这个关键字,则表明不限制一定要通过连接Tracker来获取peer

     

 

对于单文件模式的种子文件,info的值还含有的关键字如表13-3所示。

13-3                                                 单模式种子文件的关键字

    

    

name

共享文件的文件名,也就是要下载的文件的文件名

length

共享文件的长度,以字节为单位

md5sum

可选,它是共享文件的md5值,这个值在BT协议中根本没有使用,所以不必理会

对于多文件模式的种子文件,info的值还含有的关键字如表13-4所示

13-4                                             多文件模式种子文件的关键字

    

    

name

存放所有共享文件的文件夹名

files

它的值是一个列表,列表中含有多个字典,每个共享文件为一个字典。该字典中含有三个关键词

 

Files的每个共享文件为一个字典字典的关键词如表13-5所示

13-5                                                        Files字的关键诃

    

    

length

共享文件的长度,以字节为单位

md5sum

可选,同上

path

存放的是共享文件的路径和文件名

 

建议读者到一些提供BT种子文件下载的网站,如bt.greedland.netwww.btchina.net,下载几个种子文件并在Windows操作系统下使用记事本打开进行分析,就可以清楚的了解上述概念。

2.5  与Tracker交互

完成解析种子文件并从中获取Tracker服务器的URL后,即可开始与Tracker进行交互。与Tracker进行交互主要有两个目的:一是将自己的下载进度告知给Tracker以便Tracker进行一些相关的统计;二是获取当前下载同一个共享文件的peerIP地址和端口号。

客户端使用HTTP协议与Tracker进行通信。Tracker通过HTTP GET方法获取请求,请求的构成为TrackerURL后面跟一个?以及参数和值对,如http://tk.greedland.net/ announce? param1= value1&param2= value2

在客户端发往TrackerGET请求中,通常包含参数如表13-6所示。

13-6                                                        GET请求的参数

    

    

info_hash

与种子文件中info关键字对应的值,通过Sha1算法计算其hash值,该hash值就是info_hash参数对应的值,该hash值的长度固定为20字节

peer_id

每个客户端在下载文件前以随机的方式生成的20字节的标识符,用于标识自己,它的长度也是固定不变的

port

监听端口号,用于接收其他peer的连接请求

uploaded

当前总的上传量,以字节为单位

downloaded

当前总的下载量,以字节为单位

left

还剩余多少字节需要下载,以字节为单位

compact

该参数的值一般1

event

它的值为startedcompletedstopped其中之一。客户端第一次与Tracker进行通信时,该值为started;下载完成时,该值为completed;客户端即将关闭时,该值为stopped

ip

可选,将客户端的IP地址告知给TrackerTracker可以通过分析客户端发给TrackerIP数据包来获取客户端的IP地址,因此该参数是可选的,一般不用指明客户端的IP

numwant

可选,希望Tracker返回多少个peerIP地址和端口号。如果该参数缺省,则默认返回50peerIP地址和端口号

key

可选,它的值为一个随机数,用于进一步标识客户端。因为已经由peer_id来标识客户端,因此该参数一般不使用

trackerid

可选,一般不使用

Tracker服务器的返回信息是一个经过B编码的字典。它含有关键字如表13-7所示。

13-7                                           Tracker服务器返回信息关键字

    

    

failure reason

该关键字对应的值是一个可以读懂的字符串,指明GET请求失败的原因,如果返回信息中含有这个关键字,就不会再包含其他任何关键字

warnging message

该关键字对应的值是一个可以读懂的警告字符串

interval

指明客户端在下一次连接Tracker前所需等待的时间,以秒为单位

min interval

指明客户端在下一次连接Tracker前所需等待的最少时间,以秒为单位

tracker id

指明TrackerID

complete

一个整数,指明当前有多少个peer已经完成了整个共享文件的下载

incomplete

一个整数,指明当前有多少个peer还没有完成共享文件的下载

peers

返回各个peerIP和端口号,它的值是一个字符串。首先是第一个peerIP地址,然后是其端口号;接着是第二个peerIP地址,然后是其端口号;依此类推

 

以下是一个发往Tracker服务器的HTTP GET请求的示例:

http://tk.greedland.net/announce?info_hash=01234567890123456789&

peer_id=01234567890123456789&port=3210&compact=1&uploaded=0&downloaded=0&left=8000000&event=started

以下是一个Tracker服务器回应的示例:

d8:completei100e10:incompletei200e8:intervali1800e5:peers300:......e

其中,“......”是一个长度为300的字符串,含有50peerIP地址和端口号。IP地址占4字节,端口号占2字节,即一个peer6字节。

 


 

发往Tracker服务器的HTTP GET请求中,info_hashpeer_id可能含有非数字、非字母的字符,即含有除09azAZ之外的字符,此时要对字符进行编码转换。例如,空格应该转换为 。否则Tracker无法正确处理GET请求。

 

2.6  peer之间的通信协议

peer之间的通信协议又称为peer wire protocal,即peer连线协议,它是一个基于TCP协议的应用层协议。

为了防止有的peer只下载不上传,BitTorrent协议建议,客户端只给那些向它提供最快下载速度的4peer上传数据。简单地说就是谁向我提供下载,我也提供数据供它下载;谁不提供数据给我下载,我的数据也不会上传给它。客户端每隔一定时间,比如10秒,重新计算从各个peer处下载数据的速度,将下载速度最快的4peer解除阻塞,允许这4peer从客户端下载数据,同时将其他peer阻塞。

一个例外情况是,为了发现下载速度更快的peer,协议还建议,在任一时刻,客户端保持一个优化非阻塞peer,即无论该peer是否提供数据给客户端下载,客户端都允许该peer从客户端这里下载数据。由于客户端向peer上传数据,peer接着也允许客户端从peer处下载数据,并且下载速度超过4个非阻塞peer中的一个。客户端每隔一定的时间,如30秒,重新选择优化非阻塞peer

当客户端与peer建立TCP连接后,客户端必须维持的几个状态变量如表13-8所示。

13-8                                               客户端必须维持的状态变量

   

    

am_chocking

该值若为1,表明客户端将远程peer阻塞。此时如果peer发送数据请求给客户端,客户端将不会理会。也就是说,一旦将peer阻塞,peer就无法从客户端下载到数据;该值若为0,则刚好相反,即表明peer未被阻塞,允许peer从客户端下载数据

am_interested

该值若为1,表明客户端对远程的peer感兴趣。当peer拥有某个piece,而客户端没有,则客户端对peer感兴趣。该值若为0,则刚好相反,即表明客户端对peer不感兴趣,peer拥有的所有piece,客户端都拥有

peer_chocking

该值若为1,表明peer将客户端阻塞。此时,客户端无法从peer处下载到数据。该值若为0,表明客户端可以向peer发送数据请求,客户端将进行响应

peer_interested

该值若为1,表明peer对客户端感兴趣。也即客户端拥有某个piece,而peer没有。该值若为0,表明peer对客户端不感兴趣

 

当客户端与peer建立TCP连接后,客户端将这几个变量的值设置为。

am_chocking     = 1

am_interested  = 0

peer_chocking  = 1

peer_interested = 0

当客户端对peer感兴趣且peer未将客户端阻塞时,客户端可以从peer处下载数据。当peer对客户端感兴趣,且客户端未将peer阻塞时,客户端向peer上传数据。

除非另有说明,所有的整数型在本协议中被编码为4字节值(高位在前低位在后),包括在握手之后所有信息的长度前缀。


BitTorrent协议分析二


客户端与一个peer建立TCP连接后,首先向peer发送握手消息,peer收到握手消息后回应一个握手消息。

l     握手消息是一个长度固定为68字节的消息。消息的格式如下:

<pstrlen><pstr><reserved><info_hash><peer_id>

消息格式中一些参数的含义如表13-9所示。

13-9                                                               握手消息

 

    

    

pstrlen

pstr的长度,该值固定为19

pstr

BitTorrent协议的关键字,即“BitTorrent protocol

reserved

8字节,用于扩展BT协议,一般这8字节都设置为0。有些BT软件对BT协议进行了某些扩展,因此可能看到有些peer发来的握手消息这8个字节不全为0,不过不必理会,这不会影响正常的通信

info_hash

与发往TrackerGET请求中的info_hash为同一个值,长度固定为20字节

 

peer_id与发往TrackerGET请求中的peer_id为同一个值,长度固定为20字节。一般从peer_id可以识别出BT软件的类型,例如,某peer发来的握手消息中peer_id的前8个字节为“-AZ2060-”,则可以断定对方使用的是Azureus;若为-BCxxxx-”,x为数字,则对方使用的是BitComet

对于除握手消息之外的其他所有消息,其一般的格式为:

 

<length prefix><message ID><payload>

 

length prefix(长度前缀)占4个字节,指明message IDpayload的长度和。message ID(消息编号)占一字节,是一个10进制的整数,指明消息的编号。payload(负载),长度未定,是消息的内容。

l     keep_alive消息<len=0000>

keep_alive消息的长度固定,为4字节,它没有消息编号和负载。如果一段时间内客户端与peer没有交换任何消息,则与这个peer的连接将被关闭。keep_alive消息用于维持这个连接,通常如果2分钟内没有向peer发送任何消息,则发送一个keep_alive消息。

l     choke消息<len=0001><id=0>

choke消息的长度固定,为5字节,消息长度占4个字节,消息编号占1个字节,没有负载。

l     unchoke消息<len=0001><id=1>

unchoke消息的长度固定,为5字节,消息长度占4个字节,消息编号占1个字节,没有负载。客户端每隔一定的时间,通常为10秒,计算一次各个peer的下载速度,如果某peer被解除阻塞,则发送unchoke消息。如果某个peer原先是解除阻塞的,而此次被阻塞,则发送choke消息。

l     interested消息<len=0001><id=2>

interested消息的长度固定,为5字节,消息长度占4个字节,消息编号占1个字节,没有负载。当客户端收到某peerhave消息时,如果发现peer拥有了客户端没有的piece,则发送interested消息告知该peer,客户端对它感兴趣。

l     not interested消息<len=0001><id=3>

not interested消息的长度固定,为5字节,消息长度占4个字节,消息编号占1个字节,没有负载。当客户端下载了某个piece,如果发现客户端拥有了这个piece后,某个peer拥有的所有piece,客户端都拥有,则发送not interested消息给该peer

l     have消息<len=0005><id=4><piece index>

have消息的长度固定,为9字节,消息长度占4个字节,消息编号占1个字节,负载为4个字节。负载为一个整数,指明下标为indexpiecepeer已经拥有。每当客户端下载了一个piece,即将该piece的下标作为have消息的负载构造have消息,并把该消息发送给所有与客户端建立连接的peer

l     bitfield消息<len=0001+X><id=5><bitfield>

bitfield消息的长度不固定,其中Xbitfield(即位图)的长度。当客户端与peer交换握手消息之后,就交换位图。位图中,每个piece占一位,若该位的值为1,则表明已经拥有该piece;为0则表明该piece尚未下载。具体而言,假定某共享文件共拥有801piece,则位图为101个字节,位图的第一个字节的最高位指明第一个piece是否拥有,位图的第一个字节的第二高位指明第二个piece是否拥有,依此类推。对于第801piece,需要单独一个字节,该字节的最高位指明第801piece是否已被下载,其余的7位放弃不予使用。

l     request消息<len=0013><id=6><index><begin><length>

request消息的长度固定,为17个字节,indexpiece的索引,beginpiece内的偏移,length是请求peer发送的数据的长度。当客户端收到某个peer发来的unchoke消息后,即构造request消息,向该peer发送数据请求。前面提到,peer之间交换数据是以slice(长度为16KB的块)为单位的,因此request消息中length的值一般为16K。对于一个256KBpiece,客户端分16次下载,每次下载一个16Kslice

l     piece消息<len=0009+X><id=7><index><begin><block>

piece消息是另外一个长度不固定的消息,长度前缀中的9idindexbegin的长度总和,indexbegin固定为4字节,Xblock的长度,一般为16K。因此对于piece消息,长度前缀加上id通常为00 00 40 09 07。当客户端收到某个peerrequest消息后,如果判定当前未将该peer阻塞,且peer请求的slice,客户端已经下载,则发送piece消息将文件数据上传给该peer

l     cancel消息:<len=0013><id<=8><index><begin><length>

cancel消息的长度固定,为17个字节,lenindexbeginlength都占4字节。它与request消息对应,作用刚好相反,用于取消对某个slice的数据请求。如果客户端发现,某个piece中的slice,客户端已经下载,而客户端又向其他peer发送了对该slice的请求,则向该peer发送cancel消息,以取消对该slice的请求。事实上,如果算法设计合理,基本不用发送cancel消息,只在某些特殊的情况下才需要发送cancel消息。

l     port消息:<len=0003><id=9><listen-port>

port消息的长度固定,为7字节,其中listen-port占两个字节。该消息只在支持DHT的客户端中才会使用,用于指明DHT监听的端口号,一般不必理会,收到该消息时,直接丢弃即可。

2.7  关键算法和策略

1.流水线作业

BT协议作为一种构建在TCP协议上的应用层协议,可以通过流水线作业来提高数据传输的效率。具体而言,当客户端向peer发送数据请求时(即发送request消息),一次请求多个slice(即在一个数据包中发送多个request消息请求多个slice)。假如客户端一次只发送一个slice请求,则peer给客户端发送完一个slice的数据后就进入等待,等待客户端发送新的数据请求。如果一次发送多个slice请求,则peer发送完一个slice后接着发送下一个slice,从而避免了等待,提高了数据传输的效率。事实上,HTTP协议的1.1版本就广泛地使用了流水线作业的思想,大大地提高了浏览器和Web服务器之间的传输效率。

2.片断选择算法

一个良好的片断选择策略对于提高下载速度至关重要,对于提高整个文件共享系统的性能也有重要影响。

片断选择的第一个策略是,一旦向某个peer发送对某个piece中的slice的请求后,则该piece中的其他slice也从该peer处下载,这样可以尽快地下载到一个完整的piece。因为某个peer拥有某个piece中的一个slice,则它必定拥有该piece的其他slice,并且如果peer愿意发送一个slice给客户端,它也应该愿意发送piece中的其他slice给客户端。该策略也被称为严格的优先级。

片断选择的第二个策略是,最少优先。即某个piece在所有peer中的拥有率最低,则优先下载该piece。这么做的优点是,第一,可以防止拥有这个piecepeer突然离开,导致某个piece的缺失,从而当前任何一个参与下载的peer都不能下载到一份完整的文件;第二,如果下载了某些拥有率较低的piece,则其他很多peer会向客户端请求数据,而要想从客户端下载到数据,那些peer就要提供数据给客户端下载,这样对于提高客户端的下载速度也是有帮助的。对于这个共享系统而言,优先下载拥有率较低的piece可以使得整个系统提高每个piece的拥有度,整个系统会趋向于最优。如果所有peer优先下载拥有率较高的piece,会使某些piece的拥有率进一步降低,而拥有这些低拥有率piecepeer一旦离开共享系统,则整个文件会越来越不完整,最后导致许多peer不能下载到一个完整的文件拷贝。

片断选择的第三个策略是,随机选择第一个要下载的piece。开始下载时,不能采用最少优先策略。原因在于,采用最少优先策略,如果某个piece的拥有率很低,那么下载到这个piece就相对较难。如果随机选择一个piece,那么更容易下载到该piece,一旦客户端下载到一个完整的piece,就可以提供给其他peer下载,而由于客户端向其他peer上传数据,会导致其他peer对客户端解除阻塞,从而有利于在起始阶段获得较高的下载速度。当然在下载到一些piece后,客户端应该采用最少优先策略来下载数据,这虽然会导致客户端的下载速度在短期内有所下降,但随后下载速度会有较大提高。

片断选择的第四个策略是,最后阶段模式。有时,从一个传输速度很慢的peer处下载一个piece会花费很长时间,在下载的过程中这不是什么大问题。但在下载接近完成时,如果发生这种情况,会导致客户端迟迟不能下载完成。为了解决这个问题,在最后阶段,客户端向所有peer发送对这个piece的某些slice的请求,一旦收到某个peer发来的slice,则向其他peer发送cancel消息,只从当前这个peer处下载。

3.阻塞算法

BT并不集中分配资源,每个peer有责任尽可能地提高自己的下载速度。peer从它可以连接的peer下载文件,并根据对方提供的下载速率给予同等的上传回报,对于合作者,提供上传服务,对于不合作的,就阻塞对方。阻塞是一种临时拒绝上传的策略,虽然上传停止了,但是下载仍然继续。在解除阻塞时,连接并不需要重新建立。因为阻塞过程中只是拒绝传输piece消息,其他消息,如have消息,interested消息仍可以传输。阻塞算法虽然不是BT协议一部分,但是它对提高性能是必要的。

每个客户端一直与固定数量的peer保持疏通(通常是4个),那么以什么方式来决定是否保持与某个peer疏通呢?通常的做法是,严格地根据当前的下载速度来决定哪些peer应该保持疏通。但计算当前下载速度是个大难题。当前的实现通常是计算最近10秒从每个peer处下载数据的速度。以10秒为间隔重新选择保持疏通(即解除阻塞)的peer,是为了避免频繁地阻塞和解阻塞,造成资源的浪费。实践表明,10秒足以使下载速度达到最大。

如果只是简单地为提供最高下载速率的4peer提供上载服务,那么就没有办法发现那些空闲的连接是否有更好的下载速度。为了解决这个问题,在任何时候,每个peer都拥有一个称为“optimistic unchoking(优化非阻塞)”peer,这个连接总是保持疏通状态,而不管它的下载速率是多少。每隔30秒,重新选择一个peer作为优化非阻塞peer30秒足以让该peer的上载能力达到最大。

一旦某个peer完成了下载,它不能再通过下载速率(因为下载速率已经为0了)来决定为哪些peer提供上载了。目前采用的解决办法是,优先选择那些从它这里得到更好下载速率的peer,保持与它们疏通。这样做的理由是尽可能的利用上载带宽。一旦某个peer完成了下载,那么它也就成为了种子。种子拥有一份完整的文件拷贝,并提供给其他peer下载。为了整个系统的性能,每个peer在完成下载后应该作为种子存在一段时间,作为对整个系统的回报。原始种子,即最初提供文件进行共享、并制作生成了种子文件,并把种子文件发布到Web服务器的种子,它至少应该存在到系统中生成另外一个种子时才能离开,否则当前参与下载的所有peer都不能获得一份完整的文件拷贝。

本节对BT协议的解释和分析参考了“BT协议规范”(Bittorrent Protocol Specification)BT协议设计者所著的“BT性能卓越的原因”(Incentives Build Robustness in BitTorrent)一文。

 

 

 

 

系统结构设计

 

 

 BitTorrent协议分析二

整个系统的模块结构如图13-1所示。

 

13-1  系统模块结构图

整个系统各个模块的功能如下。

1)种子解析:负责解析种子文件,从中获取Tracker服务器的地址,待下载文件的文件名和长度,piece长度,各个piecehash值。

2连接Tracker:根据HTTP协议构造获取Peer地址的请求,与Tracker建立连接,解析Tracker的回应消息,从而获取各个peerIP地址和端口号。

3)与peer交换数据:根据peerIP地址和端口号连接peer、从peer处下载数据并将已下载的数据上传给peer

4)出错处理:定义整个系统可能出现的错误类型,并对错误进行处理。

5)运行日志:记录程序运行的日志,并保存到文件中以备查看和分析。

模块“与peer交换数据”是本系统的核心和主要构成部分,它又可以划分成如下几个子模块。

1peer管理:系统为每一个已建立TCP连接的peer构造一个peer结构体。该结构体的主要成员有:peerIP地址和端口号、与该peer进行通信的套接字、该peerid、当前所处的状态、发送缓冲区、接收缓冲区、数据请求队列、数据被请求队列、从该peer处已下载的数据量和向该peer上传的数据量、下载速度和上传速度。本模块负责管理peer链表,添加和删除peer结点。

2)消息处理:peerpeer之间以发送和接收消息的方式进行通信。本模块负责根据当前的状态生成并发送消息,接收并处理消息。BitTorrent协议共定义了12种消息,其中对下载和上传数据最重要的是request消息和piece消息。request消息向peer发送数据请求,指明请求的是哪个piece的哪个slicePeer接收到request消息后根据当前的状态,决定是否发送数据给对方。如果允许发送,则构造piece消息,数据被封装在该消息中。每当下载完一个正确的piece时,就向所有peer发送have消息通告已获得该piece,其他peer如果没有该piece就可以向peer发送数据请求,每次请求都是以slice为单位。

3)缓冲管理:如果下载完一个piece就立即写入硬盘,这样会导致频繁读写硬盘,既影响速度(读写磁盘要花费较多的时间),又不利于保护硬盘(频繁读写磁盘会使硬盘寿命缩短)。为了解决这个问题,几乎所有的BT软件都在程序中增加了一个缓冲管理模块。将下载到的数据先缓存起来,等到下载到一定量的数据后再集中写入硬盘。peer请求一个slice的数据时,先将该slice所在的整个piece读入到缓冲区中,下次Peer再请求该piece的其他slice时,只常缓冲区中获取,避免了频繁读写硬盘。本模块负责维护一个16MB的缓冲区(大小可调),将下载到的数据保存在缓冲区中,并在适当时刻写入硬盘的文件中。

4)位图管理:BT协议采用位图指明当前哪些piece已经下载,哪些piece还没有下载。每个piece占一位,值为0表示该piece还未下载到,为1则表明已经下载到该piece。本模块负责管理位图,客户端与peer建立了连接并进行握手之后,即发送位图给peer告知已下载到哪些piece,同时也接收对方的位图并将其保存在Peer结构体中。每下载到一个piece就更新自己的位图,并发送have消息给所有已建立连接的peer。每当接收到peer发来的have消息就更新该peer的位图。

5)策略管理:BT协议的设计者为了保证整体性能而制定了许多策略,这些策略虽然没有写入BT协议,但已经成为事实上的标准,BT软件开发者一般都使用这些策略来保证程序的性能。本部分负责策略的管理,主要是计算各个peer的下载和上传速度,根据下载速度选择非阻塞peer,采用随机算法选择优化非阻塞peer,以及实现片断选择策略。

6)信号处理:在运行过程中,程序可能会接收到一些信号,如SIGINTSIGTERM,这些信号的默认动作是立即终止程序。这并不是所期望的。在程序终止前需要作一些处理,如释放动态申请的内存、关闭文件描述符、关闭套接字。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值