您的位置:首页 > 编程语言 > C语言/C++

用C语言开发一个BT下载软件(一) ------ BitTorrent协议 -2

2017-12-23 15:31 323 查看
与Tracker交互

      完成解析种子文件并从中获取Tracker服务器的URL后,即可开始与Tracker进行交互。交互有2个目的:

将自己的下载进度告知给Tracker以便Tracker进行一些相关统计;
获取当前下载同一个共享文件的peer的IP地址和端口号。
      客户端使用HTTP协议与Tracker通信。通过HTTP GET方法从Tracker获取请求,请求的构成为Tracker的URL后面跟一个?以及参数和值对。如http://tk.greedland.net/announce?param1=value1¶m2=value2。

      在客户端发往Tracker的GET请求中,包含以下参数:

GET请求的参数
参数 含义
info_hash与种子文件中info关键字对应的hash值(通过Sha1算法计算),其固定长度为20字节
peer_id客户端用于标识自己的标识符,随机方式生成的也是20字节hash值
port监听端口号,用于接收其他peer的连接请求
uploaded当前总的上传量(字节数)
downloaded当前总的下载量(字节数)
left还剩多少字节需要下载
compact通知服务器以何种方式返回peer,为1时,每个peer占6个字节,前4个字节为peer的IP地址,后2个为端口号
event取值为started、cmpleted、stopped之一。

       客户端第一次与Tracker通信时,该值为started;

       下载完成后,为completed;

       客户端即将关闭时,为stopped。
      Tracker服务器的返回信息是一个经过B编码的字典。包含如下关键字:

Tracker服务器返回信息关键字
关键字含义
tracker id指明Tracker的ID
complete整数,指明当前有多少个peer已经完成了整个共享文件的下载
incomplete整数,指明当前有多少个peer还没有完成共享文件的下载
peers字符串,返回各个peer的IP和端口号。各个peer的IP地址和端口号依次排列
      以下是一个发往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:incompleteei200e8:intervali1800e5:peers300;...e


      其中,“...”是一个长度为300的字符串,含有50个peer的IP地址和端口号。

peer之间的通信协议

      peer之间的通信协议又称为peer wire protocol,即peer连线协议,它是一个基于TCP协议的应用层协议。
      为了防止有的peer只下载不上传,BitTorrent协议建议,客户端只给那些向它提供最快下载速度的4个peer上传数据。客户端每隔一定时间,比如10秒,重新计算从各个peer处下载数据的速度,将下载速度最快的4个peer解除阻塞,允许这4个peer从客户端下载数据,同时将其他peer阻塞。一个例外的情况是,为了发现下载速度更快的peer,在任一时刻,客户端保持一个优化非阻塞peer。客户端每隔一定的时间,比如30秒,重新选择优化非阻塞peer。
      当客户端与peer建立TCP连接后,客户端必须维持的状态变量如下所示:

客户端需要维持的状态变量
状态变量含义
am_choking1:客户端将远程peer阻塞

0:peer未被阻塞,允许peer从客户端下载数据
am_interested1:客户端对远程peer感兴趣

0:客户端对peer不感兴趣,因为peer的所有piece,客户端都已经拥有了
peer_chocking1:peer将客户端阻塞

0:peer对客户端解除阻塞,客户端可以向peer发送数据请求
peer_interested1:peer对客户端感兴趣

0:peer对客户端不感兴趣,即客户端的所有piece,peer都已经拥有了
握手消息

      客户端与一个peer建立TCP连接后,首先向peer发送握手消息,peer收到握手消息后回应一个握手消息。握手消息是一个长度固定为68字节的消息,格式如下:
<pstrlen><pstr><reserved><info_hash><peer_id>


握手消息参数
参数含义
pstrlenpstr的长度,固定为19
pstrBitTorrent协议的关键字,即”BitTorrent protocol”
reserved占8字节,用于扩展BT协议。可忽略
info_hash与发往Tracker的GET请求中的info_hash为同一个值,固定为20字节
peer_id与发往Tracker的GET请求中的peer_id为同一个值,固定为20字节
其他消息

      握手消息意外的其他消息,其一般格式如下:
<length prefix><message ID><payload>

length prefix(长度前缀)占4个字节,指明messageID和payload的长度和。
messageID(消息编号)占1个字节,指明消息的编号。
payload(负载),长度未定,是消息的内容。

      

keep_alive消息:<len=0000>,此消息长度固定,为4字节,无消息编号和负载。本消息用于维持peer间的连接,一般2分钟内没有消息往来,则发送一条keep_alive消息。
choke消息:<len=0001><id=0>,此消息长度固定,为5字节,消息编号占1个字节,无负载。功能是发送消息的peer将接受此消息的peer阻塞。
unchoke消息:<len=0001><id=1>,此消息长度固定,为5字节,消息编号占1个字节,无负载。读,客户端每隔一定的时间,通常为10秒,计算一次各个peer的下载速度,如果某peer被解除阻塞,则发送unchoke消息。如果某peer原先是解除阻塞的,而此次被阻塞,则发送choke消息。
interested消息:<len=0001><id=2>,此消息长度固定,为5字节,消息编号占1个字节,无负载。当客户端收到某peer的have消息时,如果发现peer拥有了客户端没有的piece,则发送哦interested消息告知该peer,客户端对它感兴趣。
not interested消息:<len=0001><id=3>,此消息长度固定,为5字节,消息编号占1个字节,无负载。当客户端下载了某个piece,如果发现客户端拥有了这个piece后,某个peer拥有的所有piece,客户端都拥有,则发送not interested消息给该peer。
have消息:<len=0005><id=4><piece index>,此消息长度固定,为9字节,消息长度占4个字节,消息编号占1个字节,负载4个字节。负载为一个整数,指明下标为index的piece,peer已经拥有。每当客户端下载了一个piece,即将该piece的下标作为have消息的负载构造have消息,并把该消息发送给所有与客户端建立连接的peer。
bitfield消息:<len=0001+X><id=5><bitfield>,此消息长度不固定。X是bitfield(位图)的长度。当客户端与peer交换握手消息之后,就交换位图。位图中,每个piece占一位,若该位的值为1,表明已经拥有该piece;为0表明该piece尚未下载。
request消息:<len=0013><id=6><index><begin><length>,此消息长度固定,为17个字节,index是piece的索引,begin是piece内的偏移,length是请求peer发送的数据长度。当客户端收到某个peer发来的unchoke消息后,即构造request消息,向该peer发送数据请求。因为peer之间交换数据时以slice(长度为16KB的块)为单位的,因此request消息中length的值一般为16K。

piece消息:<len=0009+X><id=7><index><begin><block>,此消息长度不固定,index和begin固定为4字节,X为block的长度,一般为16K。当客户端收到某个peer的request消息后,如果判定当前未将该peer阻塞,且peer请求的piece,客户端已经下载,则发送piece消息将文件数据上传给该peer。
cancel消息:<len=0013><id<=8><index><begin><length>,此消息长度固定,为17个字节,len、index、begin、length各占4字节。它与request消息的作用恰恰相反,用于取消对某个slice的数据请求。如果客户端发现,某个piece中的slice,客户端已经下载,而客户端又向其他peer发送了对该slice的请求,则向该peer发送cancel消息,以取消对该slice的请求。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐