BitTorrent协议中文版(三)(0分)

  • 主题发起人 主题发起人 Another_eYes
  • 开始时间 开始时间
A

Another_eYes

Unregistered / Unconfirmed
GUEST, unregistred user!
(转载请指明作者)
(上一篇:http://www.delphibbs.com/delphibbs/dispq.asp?lid=2520630)

这部分协议是官方文档最语焉不详(而且描述混乱)的部分。以下内容纯粹属于个人理解的内容,也许存在不少理解错误的地方,只有等以后真正了解后更正了。

BT协议规定和其它客户端通讯使用TCP协议,使用client/server模式。Client连接到server后,向server请求下载数据,server响应client的请求并提供数据下载。同时client也可以响应server的数据下载请求并给server提供数据。

连接的状态:
choking状态:尽管与别人建立了连接,但是处于封锁状态(对方告诉本方:烦着呢,别理我),即不会响应本方的request(06)命令请求。
unchoking状态:会响应对方的request(06)命令请求(对方告诉本方:很乐意为您效劳)。
Interested状态:连接的对方对某些本方存在的数据感兴趣。(对方告诉本方:我爱你,别封锁(choke)我,我会向你求(request)爱的)
Not interested状态:本方不存在对方感兴趣的数据(对方告诉本方:你真老土,不过在合适的时候(unchoking时)我还是会为你提供帮助的)
连接建立后的默认状态是choking和not interested。

握手包:
client连接上server后发送的第一个包,数据格式:
|strlen|str|reserved|info_hash|peer_id|
其中:
strlen:1字节,str的长度
str:协议标识字符串,BT 协议1.0中这个字符串为“BitTorrent protocol”(咦?strlen+str部分不就是delphi中的定义:str:string[19]=‘BitTorrent protocol’嘛)
reserved:8字节,保留供扩展协议设置标记用。
Info_hash:20字节,.torrent文件中info这个dictionary的SHA1 hash值。如果server接收到的client提供的这个info_hash值与它本地.torrent文件中计算出来的不同就应当关闭该连接(呵呵,希望下载的不是同一个.torrent当然应该踢掉对方了)。
Peer_id:20字节,client的标识字符串。

建立连接后的其它通讯数据包格式:
|len|cmd|parameters/data stream|
其中:
len:4字节的Integer,指明数据包的长度(该长度包括这4个字节)
cmd:1字节的命令字段,指明该数据包的命令种类
parameters/data stream: len-5字节,根据不同的命令有不同的长度和含义(后面详细说明)。
如果len=0则表示是keepalive包,没有后面的cmd和parameters部分,用于检测连接是否已断开。接收方不需要处理这种包(当然还是需要定时发送这个包告诉对方我还活着)。

注意:数据包中所有Integer字段(包括开始的包长度len和参数中用到的Integer)都是Internet整数格式,即高位在前,低位在后。使用时需要调用ntohl这个api才能获得真正的长度。

命令字段:
00:choke命令,没有paramters部分。告诉对方已封锁对方,不会处理对方的request(06)命令请求。
01:unchoke命令,没有parameters部分。告诉对方会处理对方的request(06)命令请求。
02:interested命令,没有parameters部分。告诉对方对对方部分数据感兴趣。
03:not interested命令,没有parameters部分。告诉对方不对对方数据感兴趣。
04:have命令,parameters部分是一个Integer。告诉对方本方有某个文件块,参数指明文件块是整个文件中的第几块(从0开始),文件块就是.torrent文件中定义的一连串相同大小(除了最后一块)的piece,没有忘记.torrent文件中每块文件都对应20字节的SHA1 Hash值吧?这个hash值就是用来校验相应某块文件块是否已下载完成的,下载完成后就应当给所有连接发送本命令告诉对方本方有这块文件了。
05:bitfield命令,parameters部分的长度=.torrent文件中定义的(文件块的个数+7)/8。这个命令应当只出现一次,即当连接建立并发送/接收到握手包后的第一个包。通知对方本方所具有或不具有的各个文件块。Parameters是一个字节流,其中每个字节8个bit分别对应8个文件块,如果本地已经有了某块文件则对应bit=1,否则该bit为0,超过文件块个数的bit填0。Bit流与文件块对应关系:第一个byte的最高位对应第0块文件块,后面各bit依次类推。如果本地下载度为0%也可以不发送这个包。
06:request命令,parameters为3个Integer。向对方请求下载数据,parameters中3个integer依次表示所需要下载的文件块索引号、需要下载的这个文件块中的起始偏移和本次下载的长度。需要说明的是:BT协议要求request请求中的下载长度不得大于128k(131,072字节),如果接收到的request包中请求长度超过128k应当关闭该连接。而.torrent文件中的文件块大小一般都大于128k,常见的是256k,512k和1M,所以要下载某个文件块必须发送多次request请求才能完成。
07:piece命令,parameters为2个Integer+后续的数据流。这个命令是对对方request命令的回应。参数中2个Integer分别表示文件块索引号与文件块中的起始偏移,其后跟随的是对方请求下载的数据内容(啊,看协议来说应该允许对一个06命令回应数个07命令,只是数个07命令所包含的数据加起来才是06要求的,不过这么做似乎有点变态)。
08:cancel命令,parameters与06命令相同。该命令只可能出现在收到06命令后,表示取消对应的06命令(对方改主意了),该命令主要用于整个下载工作进行到快结束时,因为最后几个request请求可能相当慢(呵呵,应该是因为可以提供该下载的客户端太少了吧),为了提高速度,所以在下载到最后几块时可能向所有连接的机器发送最后几个的06命令(不管对方是不是unchoking的),此时接收完一块就应该向其它机器发08命令通知取消掉刚才疯狂发送的对应的06命令。

上述命令中除了06-07是一对应答命令外,所有其它命令都是通知,也就是说对方接收后不需要回应。

(待续)
 
好东西啊。
 
第四部分在那里 ?
 
继续啊。是不是最好是有个例程。
 
一次发全吧
 
后退
顶部