通常tracker会返回错误代码200.
如果返回的bencode编码中包含failure reason字段,则表示处理请求失败,此字段的值即为失败原因.
如果请求成功,则有两个字段是必须出现的:
peers:节点列表
interval:服务器期望的下次查询间隔时间,单位为秒
通常还会有如下一些字段出现:
done peers:下载完毕的节点个数
num peers或者incomplete: 当前下载的节点个数
普通模式的回复其peers字段包括ip,port两个字段,如果未指定no_peer_id参数还将包括peer id字段.
下面是普通模式的回复例子:
d8:intervali3600e5:peersld2:ip13:192.168.24.527:peer id20:{peer_id}4:porti2001eed2:ip11:192.168.0.37:peer id20:{peer_id}4:porti6889eeee
d8:intervali3600e5:peersld2:ip13:192.168.24.524:porti2001eed2:ip11:192.168.0.34:porti6889eeee
BT协议分析 收藏
一 BT系统的组成结构
1 普通的Web服务器: 例如Apache或IIS服务器
2 一个静态的种子文件: 即.Torrent文件,采用Bencoding编码
3 Tracker服务器: 追踪下载同一文件的用户
4 终端用户的Web浏览器:用于下载种子文件
5 BT客户端: 例如BitCommet,BitSpirit
二 种子文件
1 格式介绍
种子文件采用bencoding编码,整个文件包含以下关键字:
announce: Tracke服务器的UR以字符串)。
announce-list(可选): 备用Tracker服务器列表(列表)。
creation date(可选): 种子创建的时I司。
comment(可选): 备注(字符串)。
created by(可选): 创建人或创建程序的信息(字符串)。
Info: 一个字典结构,包含文件的主要信息,分二种情况:单文件结构或多文件结构
单文件结构如下:
length: 文件长度,单位字节(整数)。
md5sum(可选): 长32个字符的文件的MD5校验和,BT不使用这个值,只是为了兼容一些程序所保留!(字符串)。
Name: 文件名(字符串)。
Piece length: 每个块的大小,单位字节(整数)。
Pieces: 每个块的20个字节的SHAT Hash的值(二进制格式)。
多文件结构如下:
files: 一个字典结构。
Length: 文件长度,单位字节(整数)。
md5sum(可选): 同单文件结构中相同。
Path: 文件的路径和名字,是一个列表结构,如test\test.txt列表 为 14:test8test.txte
Name: 最上层的目录名字(字符串))o
Piece length: 同单文件结构中相同。
Pieces: 同单文件结构中相同。
2 Bencoding编码规则:
(1)字符串编码:<字符串长度>:<字符串>
例如字符串spam被编码为4:spam
(2)整数编码: i<整数>e
例如数字23表示为i23e,-23表示为i-23e,0为i0e
(3)列表编码: 1e
例如l4:spam4:eggse表示两个字符串“spam”,“eggs”
(4)字典编码: de
例如d3:cow3:moo4:spam4:eggse表示{“cow“=“moo“, “spam“=“eggs“}
d4:path3:C:\8:filename8:test.txte表示{"path"="C:\","filename"="test.txt"}
3 文件举例(以下是用记事本打开.torrent文件)
d8:announce40:udp://tracker.bitcomet.net:8080/announce13:creation datei1175422660e8:encoding3:GBK4:infod6:lengthi7080818e4:name18:gettingoveryou.mp310:name.utf-818:gettingoveryou.mp312:piece lengthi1048576e6:pieces140:琚瀲⒂!堯??M挷咲i?屩轩@鏋EU轒50-?鷰靀F?@憸%l?Iy~ ??R?襉軦d[1]f岤\>@陗罏?樯燐#o?翟木懣槾"霡瓼W?棈Dk?鰛殴鴞?チY庖}0!$苶7:privatei1ee13:publisher-url7:
三 BT系统的通信过程(没有采用DHT时)
BT客户端通过种子文件获得相关信息,在下载过程中定期与Tracker服务器交互(通过http协议或者https协议)。Tracker定期从下载者处接受信息,并返回一个Peers列表。
下载者周期性的向Tracker登记,Tracker根据各个下载者的登记信息不断更新Peers列表。因此BT客户端定时的向Tracker发出获取Peers列表的请求,以便客户端能获得更快、更多的Peers,使得它的下载速度更快。
BT客户端之间根据Peers列表的信息,向相应的BT客户端发起连接,下载需要的部分,从而实现了各个客户端之间的相互通信。这种连接是基于TCP的BT对等协议。
四 Tracker查询
Tracker通过HTTP的GET命令的参数来接收信息BT客户单发送给Tracker服务器GET请求,包含一下关键字:
Info_ hash: 种子文件中info部分的SHA-1 (Secure Hash Algorithm 1) , 20
字节长。每一个片断都采用SHA-I,当BT客户端每下载完一个片断,都需要验证数据的正确性。
PeerId: 下载者的ID,一个20字节长的字符串。每个下载者在开始一次新的下载之前,随机创建一个ID 。
IP(可选): 给出了peer的IP地址。
Port: peer所监听的端口。下载者通常在在6881端口上监听,如果该端口
被占用,就会尝试6882,如果还被占用,那么会一直尝试到6889,如果都被占用,那么就放弃监听。
Uploaded: 已经上载的数据大小。
Downloaded: 已经下载的数据大小。
Left: 该Peer还有多少数据没有下载完。
Event(可选):值可以为started, completed或stopped之一
五 Tracker响应
BT客户端向Tracker查询后,Track会发出响应。响应是用Bencoding编码的字典。
1 如果响应中有关键字failure reason,则表示查询失败,其值为一个字符串,解释失败原因。不再有其它关键字。
2 否则有两个关键字:
Interval: 两次发送请求的时间间隔
Peers: 一个字典的列表,每个字典包括一下关键字Peer Id , IP , Port,分别对应Peer所选择的ID, IP地址。
六 BT对等协议
是基于TCP的应用层协议,用于Peer之间交换信息。连接后两个Peer之间是对称的,数据可以双向传送。当一个Peer下载完一个片段后,就会向所有Peer宣布它拥有了这个片段。包括一下几个消息:
1 Handshake消息
2 Bitfield消息
3 Have消息
4 Request消息
5 Cancel消息
6 Choke消息
7 Interested消息
8 keep-alive消息
注:在没有采用DHT(Distributed Hash Table或Dynamic Hash Table)技术时,对等体之间的互相发现需要通过Tracker服务器,因此如果没有Tracker服务器,BT客户端就不会获得新加入的用户的信息,速度会受很大影响甚至根本无法下载。现在很多BT软件采用DHT技术的Kad算法,可以不通过服务器实现对等体之间的相互定位与发现,例如电驴就采用了kad网络。
BitTorrent 协议规范:
BitTorrent 是一种分发文件的协议。它通过URL来识别内容,并且可以无缝的和web进行交互。它基于HTTP协议,它的优势是:如果有多个下载者并发的下载同一个文件,那么,每个下载者也同时为其它下载者上传文件,这样,文件源可以支持大量的用户进行下载,而只带来适当的负载的增长。(译注:因为大量的负载被均衡到整个系统中,所以提供源文件的机器的负载只有少量增长)
一个BT文件分布系统由下列实体组成:
一个普通的web服务器
一个静态的“元信息”文件
一个跟踪(tracker)服务器
终端用户的web浏览器
终端下载者
理想的情况是多个终端用户在下载同一个文件。
要提供文件共享,那么一台主机需要执行以下步骤:
?运行一个 tracker服务器(或者,已经有一个tracker服务器在运行了也可以)
?运行一个web服务器,例如apache,或者已经有一个web服务器在运行了。
?在web服务器上,将文件扩展名.torrent 和MIME类型 application/x-bittorrent关联起来(或者已经关联了)
?根据 tracker服务器的 URL 和要共享的文件来创建一个“元信息”文件(.torrent)。
?将“元信息”文件发布到web服务器上
?在某个web页面上,添加一个到“元信息”文件的链接。
?运行一个已经拥有完整文件的下载者(被成为’origin’,或者’seed’,种子)
要开始下载文件,那么终端用户执行以下步骤:
?安装 BT(或者已经安装)
?访问提供 .torrent 文件的web服务器
?点击到 .torrent 文件的链接(译注:这时候,bt会弹出一个对话框)
?选择要把下载的文件保存到哪里?或者是一次断点续传
?等待下载的完成。
?结束bt程序的运行(如果不主动结束,那么bt会一直为其它人提供文件上传)
各个部分之间的连通性如下:
网站负责提供一个静态的文件,而把BT辅助程序(客户端)放在客户端机器上。
Trackers从所有下载者处接收信息,并返回给它们一个随机的peers的列表。这种交互是通过HTTP或HTTPS协议来完成的。
下载者周期性的向tracker登记,使得tracker能了解它们的进度;下载者之间通过直接连接进行数据的上传和下载。这种连接使用的是 BitTorrent 对等协议,它基于TCP。
Origin只负责上传,从不下载,因为它已经拥有了完整的文件。Origin是必须的。
元文件和tracker的响应都采用的是一种简单、有效、可扩展的格式,被称为bencoding,它可以包含字符串和整数。由于对不需要的字典关键字可以忽略,所以这种格式具有可扩展性,其它选项以后可以方便的加进来。
Bencoding格式如下:
对于字符串,首先是一个字符串的长度,然后是冒号,后面跟着实际的字符串,例如:4:spam,就是“ spam”
整数编码如下,以 ‘i’ 开始,然后10进制的整数值,最后以’e’结尾。例如,i3e表示3,I-3e表示-3。整数没有大小限制。I-0e是无效的。除了 i0e外,所以以0起始的整数都无效。I0e当然表示0。
列表编码如下,以’l’开始,接下来是列表值的编码(也采用bencoded编码),最后以’e’结束。例如:l4:spam4:eggse 表示 [‘spam’, ‘eggs’]。
字典编码如下,以’d’开始,接下来是可选的keys和它对应的值,最户以’e’结束。例如:d3:cow3:moo4:spam4:eggse,表示{‘cow’:’moo’,’spam’:’eggs’},而d4:spaml1:al:bee 表示 {‘spam’:[‘a’,’b’]}。键值必须是字符串,而且已经排序(并非是按照字母顺序排序,而是根据原始的字符串进行排序)。
元文件是采用bencoded编码的字典,包括以下关键字:
announce tracker的服务器
info 它实际上是一个字典,包括以下关键字:
Name:
一个字符串,在保存文件的时候,作为一个建议值。仅仅是个建议而已,你可以用别的名字保存文件。
Piece length:
为了更好的传输,文件被分隔成等长的片断,除了最后一个片断以外,这个值就是片断的大小。片断大小几乎一直都是2的幂,最常用的是 256k
Pieces:
一个长度为20的整数倍的字符串。它将再被分隔为20字节长的字符串,每个子串都是相应片断的hash值。
此外,还有一个length或files的关键字,这两个关键字只能出现一个。如果是length,那么表示要下载的仅仅是单个文件,如果是files那么要下载的是一个目录中的多个文件。
如果是单个文件,那么length是该文件的长度。
为了能支持其它关键字,对于多个文件的情况,也把它当作一个文件来看,也就是按照文件出现的顺序,把每个文件的信息连接起来,形成一个字符串。每个文件的信息实际上也是一个字典,包括以下关键字:
Length:文件长度
Path:子目录名称的列表,列表最后一项是文件的实际名称。(不允许出现列表为空的情况)。
Name:在单文件情况下,name是文件的名称,而在多文件情况下,name是目录的名称。
Tracker查询。Trakcer通过HTTP的GET命令的参数来接收信息,而响应给对方(也就是下载者)的是经过bencoded编码的消息。注意,尽管当前的tracker的实现需要一个web服务器,它实际上可以运行的更轻便一些,例如,作为apache的一个模块。
Tracker GET requests have the following keys:
发送给Tracker的GET请求,包含以下关键字:
Info_hash:
元文件中info部分的sha hash,20字节长。这个字符创几乎肯定需要被转义(译注:在URL中,有些字符不能出现,必须通过unicode进行编码)
Peer_id:
下载者的id,一个20字节长的字符串。每个下载者在开始一次新的下载之前,需要随机创建这个id。这个字符串通常也需要被转义。
Ip:
一个可选的参数,给出了peer的ip地址(或者dns名称?)。通常用在origin身上,如果它和tracker在同一个机器上。
Port:
peer所监听的端口。下载者通常在在 6881 端口上监听,如果该端口被占用,那么会一直尝试到 6889,如果都被占用,那么就放弃监听。
Uploaded:
已经上载的数据大小,十进制表示。
Downloaded:
已经下载的数据大小,十进制表示
Left:
该peer还有多少数据没有下载完,十进制表示。注意,这个值不能根据文件长度和已下载数据大小计算出来,因为很可能是断点续传,如果因为检查文件完整性失败而必须重新下载的时候,这也提供了一个机会。
Event:
一个可选的关键字,值是started、compted或者stopped之一(也可以为空,不做处理)。如果不出现该关键字,。在一次下载刚开始的时候,该值被设置为started,在下载完成之后,设置为completed。如果下载者停止了下载,那么该值设置为stopped。
Tracker的响应是用bencoded编码的字典。如果tracker的响应中有一个关键字failure reason,那么它对应的是一个字符串,用来解释查询失败的原因,其它关键字都不再需要了。否则,它必须有两个关键字:Interval:下载者在两次发送请求之间的时间间隔。Peers:一个字典的列表,每个字典包括以下关键字:Peer id,Ip,Port,分别对应peer所选择的id、ip地址或者dns名称、端口号。注意,如果某些事件发生,或者需要更多的peers,那么下载者可能不定期的发送请求,
(downloader 通过 HTTP 的GET 命令来向 tracker 发送查询请求,tracker 响应一个peers 的列表)
如果你想对元信息文件或者tracker查询进行扩展,那么需要同Bram Cohen协调,以确保所有的扩展都是兼容的。
BT对等协议基于TCP,它很有效率,并不需要设置任何socket选项。(BT对等协议指的是peer与peer之间交换信息的协议)
对等的两个连接是对称的,消息在两个方向上同样的传递,数据也可以在任何一个方向上流动。
一旦某个peer下载完了一个片断,并且也检查了它的完整性,那么它就向它所有的peers宣布它拥有了这个片断。
连接的任何一端都包含两比特的状态信息:是否choked,是否感兴趣。Choking是通知对方,没有数据可以发送,除非unchoking发生。Choking的原因以及技术后文解释。
一旦一端状态变为interested,而另一端变为非choking,那么数据传输就开始了。(也就是说,一个peer,如果想从它的某个peer那里得到数据,那么,它首先必须将它两之间的连接设置为 interested,其实就是发一个消息过去,而另一个peer,要检查它是否应该给这个家伙发送数据,如果它对这个家伙是 unchoke,那么就可以给它发数据,否则还是不能给它数据)Interested状态必须一直被设置――任何时候。要用点技巧才能比较好的实现这个目的,但它使得下载者能够立刻知道哪些peers将开始下载。
对等协议由一个握手开始,后面是循环的消息流,每个消息的前面,都有一个数字来表示消息的长度。握手的过程首先是先发送19,然后发送“BitTorrent protocol”。19就是“BitTorrent protocol”的长度。
后续的所有的整数,都采用big-endian 来编码为4个字节
在协议名称之后,是8个保留的字节,这些字节当前都设置为0。
接下来对元文件中的 info 信息,通过 sha1 计算后得到的 hash值,20个字节长。接收消息方,也会对 info 进行一个 hash 运算,如果这两个结果不一样,那么说明对方要的文件,并不是自己所要提供的,所以切断连接。
接下来是20个字节的 peer id。
这就是握手过程
接下来就是以消息长度开始的消息流,这是可选的。长度为0 的消息,用于保持连接的活动状态,被忽略。通常每隔2分钟发送一个这样的消息。
其它类型的消息,都有一个字节长的消息类型,可能的值如下:
‘choke’, ‘unchoe’, ‘interested’, not interested’类型的消息不再含有其它数据了。
‘bitfield’永远也仅仅是第一个被发送的消息。它的数据实际是一个位图,如果downloader已经发送了某个片断,那么对应的位置1,否则置0。Downloaders如果一个片断也没有,可以忽略这个消息。(通过这个消息,能知道什么了?)
‘have’类型的消息,后面的数据是一个简单的数字,它是下载者刚刚下载完并检查过完整性的片断的索引。(由此,可以看到,peer通过这种消息,很快就相互了解了谁都有什么片断)
‘request’类型的消息,后面包含索引、开始位置和长度)长度是2的幂。当前的实现都用的是215 ,而关闭连接的时候,请求一个超过2 17的长度。(这种类型的消息,就是当一个peer希望另一个peer给它提供片断的时候,发出的请求)
‘cancel’类型的消息,它的数据和’request’消息一样。它们通常只在下载趋向完成的时候发送,也就是在‘结束模式“阶段发送。在一次下载接近完成的时候,最后的几个片断需要很长时间才能下载完。为了确保最后几个片断尽快下载完,它向所有的peers发送下载请求。为了保证这不带来可怕的低效,一旦某个片断下载完成,它就其它peers发送’cancel’消息。(意思就是说,我不要这个片断了,你要是准备好了,也不用给我发了,可以想象,如果对方还是把数据发送过来了,那么这边必须忽略这些重复的数据)。
‘piece’类型的消息,后面保护索引号、开始位置和实际的数据。注意,这种类型的消息和 ‘request’消息之间有潜在的联系(译注:因为通常有了request消息之后,才会响应‘piece’消息)。如果choke和unchoke消息发送的过于迅速,或者,传输速度变的很慢,那么可能会读到一些并不是所期望的片断。( 也就是说,有时候读到了一些片断,但这些片断并不是所想要的)
Torrent文件解析
2009-05-11 11:37
BT种子文件使用了一种叫bencoding的编码方法来保存数据。
bencoding有四种类型的数据:srings(字符串),integers(整数),lists(列表),dictionaries(字典) 编码规则如下: (1)strings(字符串)编码为:<字符串长度>:<字符串> 例如: 4:test 表示为字符串"test" 4:例子 表示为字符串“例子” 字符串长度单位为字节 没开始或结束标记
(2)integers(整数)编码为:i<整数>e 开始标记i,结束标记为e 例如: i1234e 表示为整数1234 i-1234e 表示为整数-1234 整数没有大小限制 i0e 表示为整数0 i-0e 为非法 以0开头的为非法如: i01234e 为非法
(3)lists(列表)编码为:l>e 开始标记为l,结束标记为e 列表里可以包含任何bencoding编码类型,包括整数,字符串,列表,字典。 例如: l4:test5:abcdee 表示为二个字符串["test","abcde"]
(4)dictionaries(字典)编码为d>e 开始标记为d,结束标记为e 关键字必须为bencoding字符串 值可以为任何bencoding编码类型 例如: d3:agei20ee 表示为{"age"=20} d4:path3:C:"8:filename8:test.txte
表示为{"path"="C:"","filename"="test.txt"}
(5)具体文件结构如下: 全部内容必须都为bencoding编码类型。 整个文件为一个字典结构,包含如下关键字 announce:tracker服务器的URL(字符串) announce-list(可选):备用tracker服务器列表(列表) creation date(可选):种子创建的时间,Unix标准时间格式,从1970 1月1日 00:00:00到创建时间的秒数(整数) comment(可选):备注(字符串) created by(可选):创建人或创建程序的信息(字符串) info:一个字典结构,包含文件的主要信息,为分二种情况:单文件结构或多文件结构 单文件结构如下: length:文件长度,单位字节(整数) md5sum(可选):长32个字符的文件的MD5校验和,BT不使用这个值,只是为了兼容一些程序所保留!(字符串) name:文件名(字符串) piece length:每个块的大小,单位字节(整数) pieces:每个块的20个字节的SHA1 Hash的值(二进制格式) 多文件结构如下: files:一个字典结构 length:文件长度,单位字节(整数) md5sum(可选):同单文件结构中相同 path:文件的路径和名字,是一个列表结构,如"test"test.txt 列表为l4:test8test.txte name:最上层的目录名字(字符串) piece length:同单文件结构中相同 pieces:同单文件结构中相同 (6)实例: 用记事本打开一个.torrent可以看来类似如下内容 d8:announce35: datei1076675108e4:infod6:lengthi17799e4:name62:MICROSOFT.WINDOWS.2000.AND.NT4.SOURCE.CODE-SCENELEADER.torrent12:piece lengthi32768e6:pieces20:?W ?躐?緕排T酆ee
很容易看出 announce= creation date=1076675108秒(02/13/04 20:25:08) 文件名=MICROSOFT.WINDOWS.2000.AND.NT4.SOURCE.CODE-SCENELEADER.torrent 文件大小=17799字节 文件块大小=32768字节 |