文档说明:这个翻译版本由孤波独立完成
原文见http://bitconjurer.org/BitTorrent/protocol.html
作者:Bram Cohen
孤波对该翻译版本享有解释权和修改权
BitTorrent协议详解
BitTorrent(简称BT,比特洪流)是一个文件分发协议。它通过URL识别内容并且和网络无缝
结合。它和普通HTTP协议相比优势在于,同时下载一个文件的下载者在下载同时不断互相上
传数据,使文件源可以在很有限的负载增加的情况下支持大量下载者同时下载。
一个BT式文件分发需要以下实体:
·一个普通网络服务器
·一个静态元信息文件('Metainfo' file)
·一个BT Tracker
·一个“原始”下载者('original' downloader)
·网络终端的浏览器
·网络终端的下载者
这里假设理想情况下一个文件有多个网络终端的下载者。
架设一个BT服务器步骤如下:
1.开始运行Tracker(已运行的跳过这一步);
2.开始运行普通网络服务器程序,如Apache,已运行的跳过这一步;
3.在网络服务器上将.torrent文件关联到Mime类型
application/x-bittorrent(已做过关联的跳过这一步);
4.用要发布的完整文件和Tracker的URL创建一个元信息文件(.torrent文件);
5.将元信息文件放置在网络服务器上;
6.在网页上发布元信息文件(.torrent文件)的链接;
7.原始下载者开始提供完整的文件(原本)。
通过BT下载步骤如下:
1.安装BT客户端程序(已安装的跳过这一步);
2.上网;
3.点击一个链到.torrent文件的链接;
4.选择本地存储路径,或者选定未完成的下载的续传;
5.等待下载完成;
6.下载者退出下载(之前下载者不停止上传)。
连通性如下:
·网站正常提供静态文件,并且启动客户端上的BitTorrenthelper(这里说官方的客户端
程序);
·Tracker即时接收所有下载者信息,并且给每个下载者一份随机的peer列表。通过HTTP或
HTTPS协议实现;
·下载者定时向Tracker登记,使之知道每个人的进度,并和那些直接连接上的peer互相进
行数据的上传下载。这些连接遵循BitTorrent peer协议,通过TCP协议进行通信。
·原始下载者只上传不下载,他拥有整个文件,所以向网络中传输完文件的所有部分是很
必要的。在一些人气很旺的下载中,原始下载者经常可以在较短的时间后退出上传,因
为许多下载已经完成,并且可能依然在运行(此时相当于替原始下载者接着提供上传)。
元信息文件和Tracker的回应信息都以一种简单高效可扩展的格式(Bencoding,B编码格式
)传送。B编码过的信息就是字典和列表的嵌套(像在Python中一样),这些字典和列表包
含字符串和整型数据。它的可扩展性是因为字典中存在被忽略的关键值(key),所以附加
可选的关键值也可以在以后添加。
B编码的规则如下:
·字符串表示为前缀十进制的字符串长度加冒号再跟原字符串。
如4:spam就相当于'spam'。
·整型数据的表示是前面加'i'后面加'e'中间是十进制数,如i3e就相当于3,i-3e就是-3。
整型数据没有长度限制。i-0e无效,所有以'i0'开头的除了代表0的i0e,其它都无效。
·列表编码为一个'l'开头,后面跟它所包含的项目(已经被编码过)最后加一个'e',比如
l4:spam4:eggse 就等于 ['spam', 'eggs'] 。
·字典编码为一个'd'开头,后面是关键值(key)及其对应值轮流出现,最后加一个'e'。
如:d3:cow3:moo4:spam4:eggse 相当于 {'cow': 'moo', 'spam': 'eggs'}
d4:spaml1:a1:bee 相当于 {'spam': ['a', 'b']}
关键值必须是处理过的字符串(用原始字符串编码的,而不是数字字母混合编码的)。
元信息文件就是B编码的有以下关键值的字典(括号里面的字是简译的关键值中文意思,不
作为关键值一部分,后同):
announce(通告)Tracker的URL
info(信息)此关键值对应一个包含以下关键值的字典:
关键值name对应一个字符串,代表默认的下载文件(或保存时目录)的名字。它是纯粹建议
性的。
关键值piecelength(块长)对应文件分割成的块的字节数。出于传输需要,文件被分割成
大小相等的块,除了最后一块可能会被文件尾截断而小一些(剩下的大小不足一个块长)。
块长一般来说是2的权值,大部分设块长为256K即2的18次幂(BitTorrent官方版3.2版本以
前的默认值是1M,2的20次幂)。
关键值pieces(块)对应一个字符串,此字符串长度是20的倍数。它可以再分成每20字节一
段的多个字符串,分别对应块在相应索引中的SHA1校验码(hash)。
还有关键值length(长度)和files(文件),它们不能同时出现也不能都不出现。当length
出现说明这个元信息文件只是提供单文件下载(the single filecase),否则说明是多文
件下载(the multi-file case),载到一个目录里。单文件情况下,length对应文件长度
的字节数。多文件情况被看作是把许多单文件按文件列表中的顺序连成一个大文件下载,
而关键值files就对应文件列表,是一个字典的列表,其中每个字典又包含以下关键值:
length(长度)文件长度的字节数。
path(路径)一个包含字符串的列表,字符串就是子目录名,最后一项的字符串就是文件
本身的文件名。(一个长度为零的length表单是错误的。)在单文件情况下,关键值name
是文件名;多文件情况下,它就成了目录名。
/*****************************************************************************
*
* 与Tracker之间的通告
*
*****************************************************************************/
Tracker通告是双向的。Tracker通过HTTP协议的GET参数获得信息,然后返回一个B编码后的
信息。尽管Tracker需要在自己的服务器端执行,但它运行流畅就像Apache的一个嵌入模块。
Tracker的GET请求有如下关键值:
info_hash
20字节长的SHA1验证码,就是元信息文件中的info值中分出来的字符串进行B编码以后的信
息,是元信息文件的一个支链。这个值必须是自动转换的。
peer_id
一个20字节长的字符串,是每个用户开始新下载时随机生成的ID。这个值也必须是自动转换
的。
ip
一个非强制性的参数(可有可无)给出peer所在的IP(或DNS主机名),一般是和Tracker同
机器的原始下载者得到后用来散发文件。
port
监听端口,官方默认的是从6881端口开始试,如果端口被占用则依次向后推一个端口直到找
到空闲端口,到6889端口没找到就放弃。
uploaded
目前总上传量,编码为十进制ASCII码。
downloaded
目前总下载量,编码为十进制ASCII码。
left
还要下载的字节数,编码为十进制ASCII码。这个数不能通过文件长度和已下载数出来的,
因为文件可能是续传的,还可能有一些已经下载的数据不能通过完整性检查必须被重新下载。
event
这是个非强制性的关键值,有started,completed或stopped(或空值,等同于未运行)三
种值。如果没有这个关键值,说明下载状态的声明也会从下载者那里定期发出。首次开始下
载时发出started值,完成下载时发出completed。当文件完整后再开始,没有completed发
出,下载者中止下载时发出stopped。
Tracker的回应也是B编码字典。如果Tracker回应中有关键值failurereason(失败原因),
则对应一个人易懂的字符串信息,解释通告失败的原因,不需要其它关键值。否则,回
应必须有两个关键值:interval(间隔)对应下载者定期发出请求的间隔秒数;peers,
peers是个包含字典的列表,每个字典对应一个peer,里面包含关键值peerid、ip和port,
分别对应peer自选ID、IP地址或DNS主机名的字符串以及端口号。记住假如下载者发生一个
意外事件或者想要更多的peer列表,下载者会不定期重发请求。
如果你想对元信息文件或者Tracker通告进行扩展,请与BramCohen进行协调,确保所有扩
展都兼容。
BitTorrent的peer协议通过TCP协议进行操作,无须调节任何socket选项就可以高效运行。
peer之间的连接是对称的。两个方向收到的信息要看起来相同,数据可以流入任一方。
peer协议是说一个下载者从零开始下载,每得到元信息文件所描述的索引中的一个块且验证
码一致,就向所有peer声明已得到此块。
连接的两个终端有2个状态指标,被阻塞与否,被关注与否,阻塞(choking)别人是表明在
恢复通畅之前数据不再向对方发出。阻塞的推理和技术问题稍后会提到。
数据传输发生在一方关注对方且对方没有阻塞他的情况下。关注状态必须一致保持-如果一
个没阻塞的peer没有别人需要的数据,别人对他就会失去关注,不论自己是不是被这个peer
阻塞。完全执行这种条件可能有些狡猾,但这样的确可以让下载者知道哪些peer在阻塞消失
后可以马上开始下载。
连接开始的时候,下载者状态是“被阻塞”和“不被关注”。
当数据传输时,下载者马上将好多份对块的请求排成队列,以获得较好的TCP表现(这叫“
流水作业”)。另一方面,不能被马上写入TCP缓冲区的请求要在内存里排成队列,而不是
在一个应用程序级的网络缓冲区里,一旦阻塞出现,丢弃所有这些请求。
peer连线协议包括一次握手跟着不断的数据流,数据流来自前缀长度的信息。
peer与peer之间的握手
握手以字符十九(十进制)开始,跟着是字符串'BitTorrentprotocol'。开头的字符
是长度前缀的,希望其它新协议也能这样做以便区分。所有送入协议的整型数据都编码为
4字节高端字节序(four bytes big-endian)。头部数据之后是8个现在全部预留为0的字
节,若果你想通过改变这8个预留字节以扩展协议,请与Bram Cohen协调以保证所有扩展兼
容。然后是来自元信息文件中info值中B编码过的20字节的SHA1验证码(和info_hash向
Tracker声明的值相同,但这里是原始值那里是引用)。如果双方的值不同,连接断开。一
个例外是下载者想只用一个端口进行多个连接下载,它们会先从接入连接得到一个下载验
证码,然后和列表里面的对照,相同的那个就回应。下载验证码之后是20字节的peerid,
它包含在Tracker回应下载者的peer列表中,它是在peer向Tracker的请求中首先发出的。
如果接受方peer id不符合发送方希望,连接断开。握手完毕。
整个握手信息数据有68字节,如下:
[1 字节] 协议名称字符串长度19.
[19 字节] 协议名称字符串"BitTorrent protocol"
[8 字节] 预留全为0
[20 字节] 元信息文件的info_hash
[20 字节] 客户端自己产生的peer_id
之后是长度前缀和信息轮流出现的数据流。零长度信息用来保持连接,被忽略。这种信息一般
2分钟发一次,但是在等待数据期间超时很容易发生。
所有非保持连接用信息开头的字节(长度前缀之后的一个字节)给出类型,可能值如下:
·0-阻塞
·1-通畅
·2-被关注
·3-不被关注
·4-已有
·5-比特组
·6-请求
·7-块
·8-取消
“阻塞”、“通畅”、“被关注”和“不被关注”类信息没有荷载。
“比特组”类信息仅作为首信息发出。它负载一个比特组,下载者已有块的索引序号设同序
号数位的值设为1,其它为0。开始下载时没有任何数据的下载者跳过“比特组”类信息。首
字节高位到低位对应索引序号0-7,以此类推,第二字节对应索引序号8-15,等等。尾部的
剩余的比特位设为0。
“已有”类信息负载一个数,即刚下载并核对完验证码的块对应的索引序号。
“请求”类信息包括包含一个索引序号,开始数和长度。后两者是偏移字节数。长度一般是
2的权值除非被文件尾截断。现行一般是2的15次幂,并且关闭请求中长度大于2的17次幂的
连接。
“取消”类信息负载和“请求”类信息有一样的负载。它通常在下载接近完成即“最后阶段
(endgamemode)”发出。当下载快要完成时,剩下几个块有都从同一个通信电路下载的趋
向,这样会很慢。为了确保剩余块下载迅速,一旦还没有决定剩余块的下载请求向谁发出,
先向所有他正在从对方下载数据的连接者发送要求所有剩余块的请求。为避免低效,每当
一个块下载完成就向其他peer发出取消信息。
“块”类信息包含一个索引序号,开始数和块。记住它和“请求”类信息是相关的。当传输
速度很慢或“阻塞”“通畅”类信息快速连续发出或两者同时发生,可能会载到一个不需要
的块。下载者下载块的顺序是随机的,防止下载者与其他Peer仅有相同的块子集或超集。
做出阻塞别人的决定有很多原因。TCP协议的挤塞控制(congestioncontrol)在即时向多
连接发送信息的过程中表现极差。同时,阻塞的存在使下载者们能够用一报还一报式的算
法来确保一致的下载速率。
下面描述的阻塞算法是目前基础的配置。重要的是所有新算法不光要在包含全部扩展算法的
网络中运行良好,也要在主要包含这个基础算法的网络中运行良好。
一个优秀的阻塞算法有许多标准。它必须封锁一定上传数以获得良好的TCP表现,还要避免
频繁的堵塞和通畅交替,即所谓“纤维化”(fibrillation)。它应该用数据交换报答给自
己数据的peer。最后,它还应该偶尔尝试联一下与未连接过的peer,找出比现有连接好的连
接,这叫做尝试性疏通(optimistic unchoking)。
目前配置的阻塞算法避免纤维化的手段是每10秒转换被阻塞的peer。疏通4个自己关注且能
从他们身上得到最高下载速率的peer,进行上传从而得到回报数据,这样同时就会封闭一些
数据交换和上传数。有较高上传速率但是不被关注的peer被疏通,一旦这些peer开始下载者
被关注,那些上传率最低的peer的就被阻塞。如果下载者有了完整的文件,他用自己的上传
率而不是下载率来决定疏通谁的连接。
在任何一次尝试性疏通中都有一个peer被疏通,不管他的上传率如何(如果被关注,他会成
为4个提供下载的peer之一)。被尝试性疏通的这种peer每30秒轮换一次。刚开始下载的
peer会有大约其他人三倍的机会被尝试性疏通,这样他们就得到上传一个整块的机会(从
而获取数据报答)。
部分术语对照:
protocol 协议
'Metainfo' file 元信息文件(.torrent文件)
'original' downloader “原始”下载者
key 关键值
Bencoding B编码格式
SHA1 Hash SHA1校验码
piece 块
single file case 单文件下载
multi-file case 多文件下载
choking 阻塞别人的行为
choked 被别人阻塞
interested 被关注
four bytes big-endian 四字节高端字节序
congestion control 挤塞控制(待定)
optimistic unchoking 尝试性疏通