BitTorrent
是一个由 Bram Cohen 设计的对等的(Peer-To-Peer)
文件传输协议,其官方网站是 http://www.bittorrent.com。 BitTorrent
被设计于帮助在伙伴(Peer)
之间,通过不可靠网络传输文件。
编纂本文档的目的在于详细地描述 BitTorrent v1.0 协议的内容——Bram的那一篇《BitTorrent 协议官方规范》使用通俗的语言描述了协议的规范,却未描述关于行为上的细节规则。本文档致力于使用清晰、明确的文字描述协议,以成为 BitTorrent v1.0 协议的正式规范文档,以便将来作为扩展、升级协议的参考基础。
本文档仅适用于 BitTorrent v1.0 协议本身,目前包括种子文件结构
、伙伴通信协议
以及Tracker HTTP(S) 协议
等规范。如果有更新的版本,应当在另一番专门的文档里对其进行描述,而非本文档内。
为了清晰、明确地表述,本文档中使用了一定量的术语,如下:
BitTorrent: 指 BitTorrent 协议,下面简称 BT。
伙伴(Peer)与BT客户端(Client): 本文档中,伙伴是指一切参与下载(上传)活动的BT客户端。因此您的BT客户端也是一个伙伴,只不过它是运行在您的本地计算机上面的。您可以认为它们就是彼此相连的大量客户端。
分片(Piece)与数据块(Block): 本文档中,一个分片是一个下载单元,每个分片都有独立的SHA1校验码,这些校验码储存在元信息文件中(即种子文件)。数据块是下载时从伙伴处传来的一段段的数据,一个或者多个数据块凑成一个分片。
行业标准: 本文档中,斜体字标注的内容,表示在多个BT客户端软件中已经使用的,约定俗成(既成事实)的规范。
为了帮助读者了解本文档的改动记录,请在本文档的最后一章节填写修改记录。
BEncoding 是一种用于组织、描述数据的简洁编码格式,它支持 4 种数据类型:字节串(Byte String)、整数(Integer)、列表(List, 线性表)、字典(Dictionary)。
BEncoding 使用不同的格式描述上述类型,下面逐一介绍:
为了方便表述,在本文中,每个使用 BEncoding 编码的数据称为 BE量,而 BEncoding 则简称 BE。
字节串(Byte String)
字节串的格式为 字节串长度:内容
,其中 字节串长度
是 ASCII 编码格式的整数字符串,单位为字节,例如:
4:abcd
表示4个字节的串 "abcd"
0:
表示0个字节的串 ""
整数(Integer)
整数的格式为 i整数e
,其中 整数
是 ASCII 编码格式的整数字符串,例如
i1234e
表示整数 1234
i-1e
表示整数 -1
注意:
i-0e
是无效编码;- 除了
i0e
之外,一切以0开头的整数如i03e
,i011e
都是无效的编码;- 虽然并未规定整数类型的最大值,但是 64位 整数的支持是强制的、必不可少的,以支持超过 4GB 大小的文件。
列表(List, 线性表)
列表的格式为 l不限数量个BE量e
(小写L开头),例如:
l4:spam4:eggse
表示 [ "spam", "eggs" ]
li123e5:helloi111ee
表示 [ 123, "hello", 111 ]
le
表示 [] 空列表
字典(Dictionary)
字典的格式为 d不限数量个字段e
(小写D开头)。字段 是指一种 key-value 结构,其中 key 是一个BE字节串,一个字段的格式为 一个BE字节串+一个BE量
例如:
d3:cow3:moo4:spam4:eggse
表示 { "cow" => "moo", "spam" => "eggs" }
d4:name5:Angus3:agei23ee
表示 { "name" => "Angus", "age" => 23 }
d4:spaml1:a1:bee
表示 { "spam" => [ "a", "b" ] }
d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee
表示 { "publisher" => "bob", "publisher-webpage" => "www.example.com", "publisher.location" => "home" }
de
表示一个空字典 {}
注意:key 是 BE字节串,而不是字符串,因此 key 的比较是二进制比较而不是字符串比较。
- C by Mike Frysinger
- C
- C# by SuprDewd
- C# by LordMike
- Clojure by nakkaya
- Common Lisp by osa1
- Elixir by Rodney Folz ...
更多查看原文 BEncoding 的多种语言实现。
第三篇:种子文件结构
译者注:Metainfo,即,元信息,是一种专门用于“描述属性的信息”。种子文件(.torrent files)的学名叫元信息文件(Metainfo File),表示其内只有对应文件资源的元信息,因而没有真实的文件数据。一个种子文件内包含了一个或多个文件资源的元信息。
元信息文件(Metainfo File),就是我们所知道的种子文件(.torrent files),是一个 BEncoding 编码的数据文件,其整个文件的内容是一个 字典,包含如下 字段。
info
字典,描述种子内包含的文件列表信息,这里有两种类型,一是单文件的,二是多文件的,具体看后面的说明。announce
字节串,描述 Tracker 的 URL。announce-list
列表,可选,这是一个对官方规范的扩展项(参考文档:announce-list扩展字段的申请稿),提供后向兼容。creation date
字节串,可选,这是一个UNIX时间戳,表示种子文件的创建时间。comment
字节串,可选,自由描述字段,一般描述种子的制作者。created by
字节串,可选,描述用于制作这个种子文件的程序。encoding
字节串,可选,描述 info.pieces 字段的编码方式。info 字典
无论是单文件格式还是多文件格式的种子文件,其 info 字段下都可以包含以下 3 个字段:
piece length
整数,表示一个分片的长度(单位:字节),称之为 分片单位。pieces
字节串,是由多个分片的 SHA-1校验码(20字节/个) 拼凑而成的字节串,因此其长度总是为20的倍数。
private
整数,可选,如果这个值被置为1,那么 BT客户端 必须通过向 种子文件 中指定的 Tracker 汇报自身的存在,从而获取其它 伙伴 的信息。反之如果置0,客户端 可以通过其它方法获取其它伙伴,例如 PEX,DHT。因此,private 字段也可以理解为“禁止通过其它途径获取伙伴信息”。注意:Private Tracker 存在诸多争论。
参考文档:private 扩展字段的申请稿。
Azureus(BT客户端软件)最先支持了 private 字段。
单文件格式的 info 字典字段内容
当种子内仅包含一个文件的信息时,其 info 字段 内必须包括如下字段:
name
字节串,种子内包含的唯一文件的名称,这不是强制性的命名,仅作参考。(下载时可以修改保存的文件名)length
整数,种子内包含的唯一文件的大小,单位是字节。md5sum
字节串,可选,这是一个32位的16进制字符串,表示种子内包含的唯一文件的 MD5 校验值。尽管几乎所有BT客户端都未使用到这个字段,但是它仍被保留作为兼容性字段。多文件格式的 info 字典字段内容
当种子内包含多个文件的信息时,其 info 字段 内必须包括如下字段:
name
字节串,种子内所有文件的总名称,BT客户端下载时默认使用它作为资源的目录名称,同理,这不是强制性的命名,仅作参考。(下载时可以修改保存的目录名)files
列表,这是一个由多个字典组成的列表,每个 字典 对应一个文件的信息,这些字典的格式如下:
length
整数,文件的大小,单位是字节。md5sum
字节串,可选,这是一个32位的16进制字符串,表示该文件的 MD5 校验值。尽管几乎所有BT客户端都未使用到这个字段,但是它仍被保留作为兼容性字段。path
列表 这是一个特殊的文件路径表示方式。假设一个文件在种子内对应的相对路径是a/bb/ccc/hello.txt
,那么将其根据/
分割开,得到顺序列表[ 'a', 'bb', 'ccc', 'hello.txt' ]
,经过 BEncoding 编码后就是l1:a2:bb3:ccc9:hello.txte
。注意
piece length
,即 分片单位 一般是 2 的 N 次幂。分片单位 通常根据资源文件的总体积选择,分片单位 太大会降低文件传输的效率,太小则导致 种子文件 的体积增大。从经验上看,选择 分片单位 的依据是能否将种子文件的体积控制在约 50 - 75 kB 之间(估计是为了减小服务器负担)。
- 按目前的经验看来,最适合的 分片单位 是
512kb
,尽管这个大小可能导致大体积资源的种子文件体积增大,但是却能提高文件传输的效率。常用的 分片单位 有256kb
,512kb
和1MB
。- 除了最后一个 分片 可能不同,其它每一个 分片 大小都是相同的。因此 分片 的总数等于
ceil(资源总体积 / 分片单位)
。- 对于多文件的情况,请考虑把多个文件按照字段
info.files
里的顺序将每个文件拼接成一个长数据流,即把整个资源视为一个文件处理。这样一来,两个文件之间的边界,就可能落在同一个 分片 内。每一个 分片 都有对应的 SHA-1 哈希值。将所有的这些哈希值按顺序串联起来,就得到了
info.pieces
字段。注意info.pieces
是字节串,而不是列表。因此根据 SHA-1 哈希值的长度为 20 字节可以确定,info.pieces
的长度一定是 20 的倍数。第四篇:Tracker 协议
Tracker 是一个基于 HTTP(S) 的服务器,通过 HTTP GET 的方法提供服务。BT客户端通过 HTTP GET 请求,发送上传、下载相关的信息到 Tracker,以助于 Tracker 统计种子的数据信息。请求的返回数据中,包括当前参与该种子上传、下载的伙伴信息列表。
Tracker 的 URL 被包含在种子文件中,即 announce 字段,而请求携带的参数则添加到 URL 的 queryString 中。
注意:二进制参数必须转义为 URL 标准编码格式。这意味着除
[-0-9A-Za-z\._~]
之外的字符都将被转义为形同%nn
的十六进制格式。参考 RFC1738。Tracker 请求参数说明
- info_hash 种子文件的 info 字段的 SHA-1 校验值。
- peer_id 表示请求者(BT客户端)的唯一 ID,一般是客户端在启动时生成的 20 字节字符串。此值不限制格式,任意二进制值都是可以的。但由于 peer_id 没有相关的产生准则,因此它仅被假定在您的本地计算机上是唯一的。
- port BT客户端 监听的网络端口号,一般是
6881-6889
,当然也可以监听其它的端口。- uploaded 自上一次向 Tracker 发送
event=start
请求之后,BT客户端 (对于该种子)的总上传字节数,以十进制整数 ASCII 字符串表示。- downloaded 自上一次向 Tracker 发送
event=start
请求之后,BT客户端 (对于该种子)的总下载字节数,以十进制整数 ASCII 字符串表示。
MemoNet:用codebook记住所有的交叉特征来做CTR估计Memorizing All Cross Features’ Representations Efficiently via