BT结点间通信协议

1.结点状态,结点对每个连接保存了四个布尔值:

amchoking:对方被阻塞

aminteresting:对对方感兴趣

amchoked:被对方阻塞

aminterested:对方对自己感兴趣

2.数据块结构

BT系统中目标文件被分成256KB的小块,便于在结点之间交换。实际上,这些数据块又被分为子块,一般一块为16KB,结点之间传送的是16KB的子块,这样可以更好的利用带宽。结点在某一块内可以按任意顺序下载子块,但是不会跨块下载不同块内的子块,这是因为整块数据需要用摘要验证正确性,而只有验证正确的数据才能提供给其他结点下载,为了尽快共享整块数据,就应该尽量把一整块下载完整,再下载其他的块。块在整个目标文件中是按顺序排列的,每个块都有编号,结点之间使用数据块编号来定位数据块,每一块都有对应的摘要,存储在Torrent文件中:而子块是用在块中相对于块头的偏移和子块数据的长度来定位的,称为子块偏移和子块长度。

3.结点间传输的消息

结点之间开始传输数据之前,有一个握手过程,这个过程可以过滤掉非BT程序的误连。握手过程中双方互相发送一个TCP包,内容如下所示:

 

 

Pstrlen(1)

 

Pstr(19)

 

Reserved(8)

 

Info_hash(20)

 

Peer_id(20)

 

其中psrt是一个字符串“BiTTorrent portocol”,prstlen是psrt的长度,也就是19;reserved是留给扩展协议用的,一般都是0;info_hash与发给追踪器的info_hash是相同的,peer_id也与发给追踪器的peer_id相同(其他结点从追踪器得到的对应的peer_id与这个值相同)。经过握手之后,两个结点之间就可以开始互相发送消息了,可发送的消息格式有10种,格式如下表:

 

 

name

Lengthprefix(4)

Messageid(1)

Payload

 

Keep alive

 

0000

 

 

 

Choke

 

0001

 

0

 

 

Unchoke

 

0001

 

1

 

 

Interested

 

0001

 

2

 

 

Not interested

 

0001

 

3

 

 

Have

 

0005

 

4

 

1个整数

 

Bitfield

 

不定

 

5

 

不定长

 

Request

 

000D

 

6

 

3个整数

 

Piece

 

不定

 

7

 

不定长

 

Cancel

 

000D

 

8

 

3个整数

 

其中length prefix是一个4位的整数,表示后面的message ID与payload的总长度;message ID是消息号,长度固定为1位,payload是负载,存储其他信息,长度不定。消息可按照长度分为3类,第一类为空消息,也称为keep alive消息,空消息没有消息号和负载。结点发送空消息的目的是保证对方依然在线。如果对方在线,会回发一个TCP头上带ACK标志的空消息;第二类是通知消息,只有消息号,没有负载,消息长度固定为1。通知消息包括消息号为0-3的4种消息,结点通过这几个消息通知对方设置阻塞和感兴趣两个值。第三类是数据消息,剩下的5种消息都是属于这一类,这些消息负责结点之间的数据传输。

(1)have消息

结点在下载某一块数据结束时,向所有己连接的结点发送have消息,通知其他结点自己已经有这块数据,可以提供下载,have消息的负载是数据块的编号。

(2)bitfield消息

在握手之后,如果结点己经有部分数据,那么向对方发送bitfield消息来描述己有数据,bitfield消息只能在握手之后,所有其他消息发送前发送。不过bitfield消息是可以省略的,如果结点没有任何数据,可以不发送bitfield消息。bifield消息的负载描述了该结点己有的数据,第一个字节的最高位表示第一块数据,也就是编号为0的数据块,后面每一位表示下一块数据。如果某一位为0,表示结点没有对应的数据块,如果某一位为1,表示结点己经有对应的数据块。如果最后的字节不满8位,剩下的位用0填充。

(3)request消息

结点要从某结点下载数据时,向这个结点发送request消息。request消息的负载是三个整数,分别是数据块编号、子块在数据块内的偏移、以及子块长度。

(4)piece消息

piece消息进行实际的数据传输。结点要回应request消息,就发送piece消息。piece消息的负载是数据块编号、子块偏移以及子块内容。

(5)cancel消息

cancel消息是在“结束模式”下发送的,“结束模式”中结点向所有结点发送request消息请求下载某子块,当子块下载完成时,就不需要从其他结点再下载这一子块了,结点给其他所有结点发送cancel消息,通知其他结点不用发送子块。cancel消息的负载与have消息完全相同,数据块编号、子块偏移、子块长度。

 

猜你喜欢

转载自xinaction.iteye.com/blog/1219344