BitTorrent协议规范中文.docx
《BitTorrent协议规范中文.docx》由会员分享,可在线阅读,更多相关《BitTorrent协议规范中文.docx(20页珍藏版)》请在冰豆网上搜索。
BitTorrent协议规范中文
BitTorrent协议规范try
维基百科,自由的百科全书
BitTorrent是由布莱姆·科恩设计的一个点对点(P2P)文件共享协议,此协议使多个客户端通过不可信任的网络的文件传输变得更容易。
目录
∙1目的
∙2应用范围
∙3约定
o3.1B编码
▪3.1.1字节串
▪3.1.2整数
▪3.1.3表
▪3.1.4字典
∙4元信息文件结构
∙5服务器HTTP/HTTPS协议
∙6服务器“刮”约定
∙7用户线路协议(TCP)
o7.1概述
o7.2数据类型
o7.3消息流
o7.4握手
▪7.4.1peer_id
o7.5消息
∙8算法
o8.1排队
o8.2超级种子
o8.3片断下载策略
o8.4最后阶段
o8.5阻塞与最佳畅通
o8.6反冷落
∙9相关文档
∙10请参阅
目的
此规范的目的是详细介绍BitTorrent协议规范v1.0。
Bram的协议规范网站简要地叙述了此协议,在部分范围缺少详细行为阐述。
希望此文档能成为一个正式的规范,明确的条款,将来能作为讨论和执行的基础。
此文档规定由BitTorrent开发者维持和使用。
欢迎大家为它做贡献,其中的内容代表当前协议,它仍由许多客户使用。
这里不是提出特性请求的地方。
如果有请求,请见邮箱列表。
应用范围
本文档适用于BitTorrent协议规范的第一版(v1.0)。
目前,这份文档应用于torrent文件结构、用户线路协议和服务器(Tracker)HTTP/HTTPS协议规范。
如果某个协议的修改有了新的定义,它们会被指定在协议相应的页面,而不在这里。
约定
在本文档中,使用了许多约定来简明和明确地表达信息。
∙用户(peer)v/s客户端(client):
在本文档中,一个用户可以是任何参与下载的BitTorrent客户端。
客户端也是一个用户,尽管BitTorrent客户端运行在本地机器上。
本规范的读者可能会认为自己是连接了许多用户的客户端。
∙片断(piece)v/s块(block):
在本文档中,片断是指在元信息文件中描述的一部分已下载的数据,它可通过SHA-1hash来校验。
而块是指客户端向用户请求的一部分数据。
两块或更多块组成一个完整的片断,它能被校验。
∙实际标准:
大的斜体字文本指出普通的准则在不同客户端BitTorrent的执行,它被当作为实际标准。
为了帮助其他人找到本文档最近的修改,请填写改变日志(最后一段)。
它应包含一个简短的项目(如:
一行),用来记录你每次对此文档的主要改动。
B编码
主条目:
Bencode
B编码是一种以简洁格式指定和组织数据的方法。
支持下列类型:
字节串、整数、表和字典。
字节串
字节串按如下编码:
<以十进制ASCII编码的串长度>:
<串数据>
注意没有开始和结束的分隔符。
例:
“4:
spam”代表字符串“spam”
整数
整数按如下编码:
i<以十进制ASCII编码的整数>e
开始的“i”与结尾的“e”分别是开始和结束分隔符。
可以使用如“i-3e”之类的负数。
但不能把“0”放到数字的前面,如“i04e”。
另外,“i0e”是有效的。
例:
“i3e”代表整数“3”
表
表按如下编码:
l<编码值>e
开始的“l”与结尾的“e”分别是开始和结束分隔符。
表可以包含任何已编码的类型,包括整数、串、字典和其他的表。
例:
l4:
span4:
eggse代表两个串的表“spam”、“eggs”
字典
字典按如下编码:
d<编码串><编码元素>e
开始的“d”与结尾的“e”分别是开始和结束分隔符。
注意关键字必须被编码为串。
值可以是任何已编码类型,包括整数、串、表和其他字典。
关键字必须是串,以分类的顺序出现(以原始串排列,而不是以字母数字)
例1:
d3:
cow3:
moo4:
spam4:
eggse代表字典{"cow"=>"moo","spam"=>"eggs"}
例2:
d4:
spaml1:
a1:
bee代表字典{"spam"=>["a","b"]}
元信息文件结构
所有在元信息文件中的数据都要编码。
编码规则如上所述。
元信息文件(以.torrent结尾的文件)的内容是一个编码的字典,包含以下列表中的各项。
所有字符串值都以UTF-8编码。
标记没有为“可选”的键值是必需的字段:
∙信息
一个描述torrent文件的字典。
有两种可能的形式:
一种是没有目录结构的“单一文件”,另一种是包含子目录树的“多文件”
对于“单一文件”来说,信息字典包含以下的结构:
长度:
文件字节数长度(整数)
md5和:
(可选)一个32位的16进制字符串,它对应于文件的MD5和。
不被BitTorrent所使用,但被一些程序包含,以提供更大的兼容性。
名称:
文件的名称。
建议使用(字节串)。
片断长度:
每个片断的字节数(整数)。
片断:
包含所有20字节SHA-1散列值的字符串,每个片断都有唯一的值。
(字节串)
对于“多文件”来说,信息字典包含以下的结构:
文件:
字典列表,每个文件都有一个。
每个在表中的字典包含以下键值:
长度:
文件长度的字节数(整数)
md5和:
(可选)一个32位的16进制字符串,它对应于文件的MD5和。
不被BitTorrent所使用,但被一些程序包含,以提供更大的兼容性。
路径:
一个包含着一个或多个字符串元素的,它包含路径和文件名。
每个表中元素对应于一个目录名或(在最后的元素的情况下)文件名。
例:
文件名“dir1/dir2/file.ext”将包含三种串元素:
“dir1”、“dir2”和“file.ext”。
编码为串表的例子“l4:
dir14:
dir28:
file.exte”
名称:
结构中根目录的名称--包含上述文件列表中所有文件的目录(字符串)
片断长度:
每个片断的字节数(整数)。
片断:
包含所有20字节SHA-1散列值的字符串,每个片断都有唯一的值。
(字节串)
∙发布:
服务器的发布URL(字符串)
∙发布列表:
(可选)这是官方规范的一个扩展,它是向后兼容的。
此键值用来执行备份服务器的列表。
完整的规范可在找到。
∙创建日期:
(可选)torrent文件的创建时间,使用标准Unix时间格式(从UTC1970年1月1日00:
00:
00开始,整数秒)
∙评论:
(可选)发布者的自由评论(字符串)
∙由……创建:
(可选)创建torrent文件的名字和程序版本(字符串)
注意:
∙片断长度指定了标准的片断大小,通常是2的n次方。
片断长度的一般是根据torrent文件中所有数据的数量来决定的,如果片断太大,会导致效率低,出错概率增加;而如果太小,则会使生成的torrent元数据文件过大。
常识决定使用最小的片断大小,这样就会使生成的torrent文件不大于50-75KB(可以减轻存储torrent文件服务器的负担)。
但是,由于没有严格限制存储和带宽,即使为了高效率的共享文件可能导致生成更大的torrent文件,也建议将小于8-10GB文件的片断大小设为小于或等于512KB。
通常大小是256KB,512KB和1MB。
除了最后的片断大小不定以外,其余片断大小是相等的。
因此片断的数目由总大小决定。
对于多文件模式下的片断边界,将文件数据设想为一个长的连续流,由文件有序列表中的每个文件相互连接而成。
片断数目和其边界的决定方式与单一文件相同。
片断可能由两个文件的边界组成。
∙每个片断都有相应的SHA-1hash数据校验码。
这些校验码相互连接形成上述的信息字典的片断值。
注意这不是一个表,而是一个字符串。
其长度必须是20字节的整数倍。
服务器HTTP/HTTPS协议
服务器是用类响应HTTPGET请求的一种HTTP/HTTPS服务。
该请求包括客户端的度量标准,这个标准可以帮助服务器全面统计torrent文件。
基本的URL包括元数据文件(torrent)中定义的“发布URL”。
再将那些参数通过标准CGI方法添加到此URL中(如:
“?
”在发布URL之后,紧接着“参数=值”的序列,分隔符“&”)
注意所有在URL中的二进制数据(特别是info_hash和peer_id)必须使用转义符。
这意味着除0-9,a-z,A-Z和$-_.+!
*'()外,其余字节需要采用“%nn”格式的编码,其中的“nn”是字节的16进制数值。
(详细见RFC1738)
客户端向服务器的GET请求的参数如下:
∙info_hash:
元信息文件中20字节的SHA-1散列值。
注意此值会进入编码字典中,如上述的信息关键字的定义所述。
与不需编码的peer_id相比,它总是被URL编码。
∙peer_id:
客户端ID,客户端用来唯一标识自己ID的20字节的串,它在客户端启动时生成。
允许为任何值,包括二进制数据。
目前没有特定的算法来生成客户端ID。
但是,人们会认为它至少对于自己的本地机器是唯一的,从而应该像进程ID一样合并数据,也可能在启动时由时标记录。
见本区域下面的一般客户端编码的peer_id。
∙端口:
客户端监听的端口号。
BitTorrent所使用的典型端口是6881-6889。
如果此范围的端口都无效,可以选择其他的。
∙已上传的:
从客户端发送“已开始”事件到服务器算起的上传总量,数值采用10进制的ASCII。
对于没有在官方规范明确指出的,该值应为已上传的字节总数。
∙已下载的:
从客户端发送“已开始”事件到服务器算起的下载总量,数值采用10进制的ASCII。
对于没有在官方规范明确指出的,该值应为已下载的字节总数。
∙剩下的:
客户端需要下载的字节数,以10进制ASCII编码。
∙紧密的:
客户端接受一个紧密的响应。
客户端列表由客户端串代替,此串中每个客户端都编码成6字节。
前4字节是主机名(以网络的字节顺序),后两个字节是端口号(同样以网络字节的顺序)。
∙事件:
如果被指定,则是已开始,已完成,已停止中的一个,或者为空(表示未指定)。
如果未指定,此请求为常规时间间隔中的一次运行。
∙
o已开始:
向服务器发送的第一个请求,必须包含开始值的事件关键字。
∙
o已停止:
如果客户端关机则须发送到服务器上。
∙
o已完成:
完成下载时必须发送到服务器上。
但是,当客户端启动时下载完成度为100%(即:
做种中)则不会发送。
可能这是允许服务器增加“已完成下载”的方法。
∙ip:
可选。
客户端的真实IP地址,以点分四元组格式或RFC3513中定义的16进制IPv6地址。
注意:
大体上此参数没有客户端地址重要,它能由IP地址决定,HTTP请求也来自该处。
仅在请求参与的IP地址不是客户端的IP地址的情况下才需要。
这种情况发生在客户端通过代理服务器与服务器进行通信的情形。
当客户端和服务器同时处在本地NAT网关时也需要。
原因是服务器会发出客户端的内部地址(RFC1918),这是不可到达的。
所以客户端必须清楚地把自己的外部可到达的IP地址发送到其他客户端中。
不同的服务器对此参数的解释有所不同。
某些只有当请求参与的IP地址属于RFC1918时才允许。
有些无条件允许,但有些则完全忽略。
如果使用IPv6地址(如:
2001:
db8:
1:
2:
:
100),则表示客户端能通过IPv6进行通信。
∙需求数目:
可选。
客户端想从服务器接收的用户数目。
允许此值为“0”。
如果不用此项,则默认值为50个用户。
∙关键字:
可选。
一个不与任何用户共享的另外的标识。
当IP地址改变后,允许客户端证明它们的标识。
∙服务器id:
可选。
如果先前发布包含服务器的id,它应放在这里。
服务器作出“text/plain”文档的响应包括以下编码字典的关键字:
∙失败原因:
如果当前使用此值,则其余关键字不会使用。
该值是可读的错误消息,包括请求失败的原因。
(字符串)
∙警告消息:
(新)与失败原因相似,但响应仍然会被正常处理。
警告消息看起来像错误。
∙时间间隔:
以秒计算,是客户端发送规则请求到服务器之后等待的时间。
(强制)
∙最小时间间隔:
最小发布时间间隔。
当前客户重发间隔不能小于此值。
∙服务器id:
一个客户端应在下一个通告发回的字符串。
如果没有该值,先前通告会发出一个服务器id,不要丢弃旧的值,一直使用它。
∙完成:
拥有完整文件的用户数,即做种者(整数)
∙未完成:
非种子用户的数目,也叫“吸血者”(整数)
∙用户:
是字典的列表,每个值都有如下的关键字:
∙
o用户id:
用户的自选择ID,如上述用来发送服务器请求的(字符串)
∙
oip:
用户的IP地址(IPv4或IPv6格式)或域名(字符串)
∙
o端口:
用户的端口号(整数)
如上所述,用户列表长度默认值为50。
如果连接的用户少于该值,列表会更小。
另外,服务器随机选择用户及其响应。
服务器在响应请求时可能使用一个更智能的机构来选择用户。
例如,应避免向其他做种者报告种子。
在事件发生(即:
已停止或已完成)或客户端需要连接更多的用户时,客户端向服务器发送请求的间隔可以低于指定的时间间隔。
但是,为了获得更多的用户而向服务器频繁地请求会被认为是错误的行为。
如果客户端想在回应中得到许多用户,则需要在“需求数目”参数中设定。
使用者注意:
30个用户就算丰富的源了,官方客户端版本3(v3)实际上在连接数少于30时会尝试增加新的连接,当连接数大于或等于55时会拒绝连接多余的用户。
这个值对性能很重要。
当完成下载一个新的片断时,“已拥有”消息(见下面)将会发送到最活动的用户。
结果广播通信量与用户数目成正比例增加。
大于25时,新用户不太可能会增加下载速度。
有人强烈建议用户界面设计者使该项模糊和很难修改,因为那样做几乎没有用。
服务器“刮”约定
根据惯例,多数服务器支持请求的另一种形式,这种方式询问给定的服务器正在处理的torrent(或所有的torrent)。
通常叫做“刮页”,因为它自动处理“刮屏”(服务器统计页)冗长的部分。
刮URL也是一种类似于上面描述的HTTPGET方法。
但基本URL不同。
用以下步骤来得到刮URL:
从发布URL开始寻找其中最后一个“/”。
如果在文本之后的“/”不是“announce”,它将被作为一个符号,此符号不支持刮约定。
如果是,则以“scrape”代替“announce”来找到刮页。
例:
(发布URL->刮URL)
->->->->(不支持刮)->->(不支持刮)->(不支持刮)
特别注意:
结束引语没有完成。
此标准是由Bram在BitTorrent开发列表文件中说明的。
刮URL可以作为可选参数“info_hash”的一个补充,是一个20字节的值。
这限制了服务器向特殊种子汇报。
另外,服务器正在处理的所有种子的统计也被发回。
为了降低服务器的负载和带宽,有人强烈建议软件作者尽可能使用“info_hash”参数。
HTTPGET方法的响应是一个由编码字典组成的“text/plain”文档,包括以下关键字:
∙文件:
每个torrent都包含一对关键字的字典,内容是统计数据。
如果添加了有效的“info_hash”,此字典将包含单个关键字。
每个关键字由一个20字节的info_hash值组成。
该关键字的值是另一个包含下列名称的嵌套字典:
∙
o已完成:
拥有整个文件的用户数目,即做种者(整数)
∙
o已下载:
服务器注册编号完成的总数(“事件=完成”,即客户端完成下载torrent)
∙
o未完成:
非做种者用户的数目,也叫“吸血者”(整数)
∙
o名称:
(可选)torrent的内部名称,由torrent文件中信息字段指定
注意此响应有三层字典嵌套。
例如:
d5:
filesd20:
....................d8:
completei5e10:
downloadedi50e10:
incompletei10eeee
其中“....................”是20字节的info_hash,以上表明有5个做种者,10个吸血者和50个完成下载的用户。
用户线路协议(TCP)
概述
用户线路协议使元信息文件中片断的交换变得更容易。
注意原始规范在描述用户协议时也使用术语“片断”,但与元信息文件中的术语“片断”不同。
由于该原因,术语“块”将在本规范中用来描述用户之间通过线路交换的数据。
客户端必须为每个远程用户的连接保持状态信息:
∙被阻塞:
远程用户是否阻塞此客户端。
当用户阻塞客户端时,不会响应任何请求。
客户端不应尝试发送请求块,所有未响应的请求会被远程用户丢弃。
∙感兴趣:
远程用户是否对此客户端感兴趣。
当客户端未阻塞时,远程用户将开始发送请求块。
注意这也意味着客户端需要记住自己是否对远程用户感兴趣和阻塞它。
因此,真正的列表看起来像这样:
∙am_choking:
此客户端阻塞远程用户
∙am_interseted:
此客户端对远程用户感兴趣
∙peer_chokong:
远程用户阻塞此客户端
∙peer_interested:
远程用户对此客户端感兴趣
客户端的连接以“被阻塞”和“不感兴趣”开始。
也就是:
∙am_choking=1
∙am_interested=0
∙peer_choking=1
∙peer_interested=0
当客户端对远程用户感兴趣并且远程用户未阻塞该客户端时,客户端开始下载块。
当客户端没有阻塞远程用户并且远程用户对该客户端感兴趣时,客户端开始上传块。
客户端保持通知远程用户自己是否对它们感兴趣,这是很重要的。
与每个远程用户连接的状态信息应保持最新,直到该客户端被阻塞。
这允许远程用户知道当自己未阻塞时,客户端是否会开始下载;反之亦然。
数据类型
如果不特别指定,在用户线路协议中的所有整数都会编码成4字节bigendian值。
这包括所有消息中的长前缀,它在握手之后。
消息流
用户线路协议包括初始握手。
之后,用户通过长前缀消息的交换来进行通信。
长前缀是上述的一个整数。
握手
握手是必需的消息,它一定是由客户端发送的第一条消息。
∙握手:
∙
opstrlen:
串的长度,作为单个原始字节
∙
opstr:
协议的串标识符
∙
oreserved:
8个保留字节。
当前的执行使用全〇。
字节中的每位可以用来改变协议的行为。
一封Bram的电子邮件建议首先使用末位,以使首位可用来改变末位的含义。
∙
oinfo_hash:
元信息文件信息关键字的20字节SHA-1散列值。
这与服务器请求中发送的info_hash意义相同。
∙
opeer_id:
每个客户端用来作为唯一标识的20个字节的串。
这与服务器请求中发送的peer_id意义相同。
在BitTorrent协议v1.0中:
pstrlen=19,pstr="BitTorrentprotocol"
连接的发起者应该立即发送彼此的握手信息。
即使接收者能同时提供多个torrent(torrent通过自己的info_hash来唯一标识),它也应等待发起者的握手信息。
但是,接收者在看到握手的info_hash部分后必须迅速回应。
服务器的NAT检查特性不会发送握手的peer_id字段。
如果客户端收到一个当前不能处理的握手info_hash,该客户端就会断开那个连接。
如果连接的发起者收到一个握手信息,其中的peer_id与预期的不同,那么发起者就会断开该连接。
注意发起者可能会收到来自服务器的远程用户信息,它包括远程用户注册的peer_id。
来自服务器的peer_id与握手信息中的应该相同。
peer_id
主要有两种将客户端及其版本信息编码到peer_id的方法:
Azureus型和Shadow型。
Azureus型使用如下编码:
“-”,一个客户端标识使用两个字符,版本号用4个ASCII数字表示,“-”紧跟在随机数字之后。
例如:
'-AZ2060-'...
已知采用这种方法编码的客户端是:
∙'AR'-Arctic
∙'AZ'-Azureus
∙'BB'-BitBuddy
∙'BC'-BitComet
∙'BS'-BTSlave
∙'BX'-BittorrentX
∙'CD'-EnhancedCTorrent
∙'CT'-CTorrent
∙'LP'-Lphant
∙'LT'-libtorrent
∙'lt'-libTorrent
∙'MP'-MooPolice
∙'MT'-MoonlightTorrent
∙'QT'-Qt4Torrentexample
∙'RT'-Retriever
∙'SB'-Swiftbit
∙'SS'-SwarmScope
∙'SZ'-Shareaza
∙'TN'-TorrentDotNET
∙'TR'-Transmission
∙'TS'-Torrentstorm
∙'UT'-µTorrent
∙'XT'-XanTorrent
∙'ZT'-ZipTorrent
Shadow型采用如下编码:
用1个ASCII字母或数字标识客户端,3个ASCII数字标识版本号,“----”紧跟在随机数字之后。
例如:
'S587----'...
已知采用此种类型编码的客户端为:
∙'A'-ABC
∙'O'-OspreyPermaseed
∙'R'-Tribler
∙'S'-Shadow'sclient
∙'T'-BitTornado
∙'U'-UPnPNATBitTorrent
Bram的客户端现在采用的形式:
'M3-4-2--'
BitComet则不同。
它的peer_id由四个ASCII字符组成“exbc”,后面是两个字节的“x”和“y”