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