[老司机]BT协议学习笔记

编码 B encode 在说明网络流程之前,先简单介绍下B encode,因为在BitTorrent协议中的数据几乎都是用B encode进行编码的。它是一种作用类似于XML和JSON的数据组织格式,可以表达字符串、整数两种基本类型,列表、字典两种数据结构,它的语法规则十分简单。 字节串按如下方式编码: <以十进制ASCII编码的串长度>:<串数据> 例:“4:spam”表示字节串“spam” 整数按如下方式编码: i<以十进制ASCII编码的整数>e 例:“i3e”表示整数“3” 列表按如下方式编码: l<内容>e 开始的“l”与结尾的“e”分别是开始和结束分隔符。lists可以包含任何B编码的类型,包括整数、串、dictionaries和其他的lists。 例:l4:spam4:eggse 表示含有两个串的lists:[“spam”、“eggs”] 字典按如下方式编码: d<内容>e 开始的“d”与结尾的“e”分别是开始和结束分隔符。注意键(key)必须被B编码为串。值可以是任何B编码的类型,包括整数、串、lists和其他的dictionaries。键(key)必须是串,并且以排序的顺序出现(以原始串排列,而不是以字母数字顺序)。 例1:d3:cow3:moo4:spam4:eggse 表示dictionary { “cow” => “moo”, “spam” => “eggs” } 元信息文件 .torrent 作为发布者,首先需要有一个域名,一台作为Tracker的服务器,一台发布.torrent文件的服务器,一台保存资源的服务器,当然这些可以共用一台服务器。使用BitTorrent工具选择“海贼王712集.mkv”文件,指定Tracker服务器的URL,会生成一个.torrent文件。 .torrent文件使用B encode表示,整个是一个字典数据结构,它有多个key值,包括一些是可选的,这里介绍最关键的几个键值对。 info:存储资源文件的元信息 piece length pieces name/path announce:描述tracker服务器的URL info键对应的值又是一个字典结构,BT协议将一个文件分成若干片,便于客户端从各个主机下载各个片。其中的piece length键值对表示一个片的长度,通畅情况下是2的n次方,根据文件大小有所权衡,通长越大的文件piece length越大以减少piece的数量,降低数量一方面降低了.torrent保存piece信息的大小,一方面也减少了下载需要对片做的确认操作,加快下载速度。目前通常是256kB,512kB或者1MB。 pieces则是每个piece的正确性验证信息,每一片均对应一个唯一的SHA1散列值,该键对应的值是所有的20字节SHA1散列值连接而成的字符串。 name/path比较笼统的说,就是具体文件的信息。因为BitTorrent协议允许将数个文件和文件夹作为一个BitTorrent下载进行发布,因此下载方可以根据需要勾选某一些下载文件。注意,这里将数个文件也砍成一个数据流,因此一个piece如果在文件边界上,可能包含不同文件的信息。 announce保存的是tracker服务器的URL,也就是客户端拿到.torrent文件首先要访问的服务器,在一些扩展协议中,announce可以保存多个tracker服务器作为备选。 生成好.torrent文件之后,发布者需要先作为下载者一样根据.torrent文件进行下载,这样就会连接到tracker服务器。由于发布者已经有了完整的资源文件,tracker服务器会得知这是一个完全下载完成的用户,会把发布者的信息保存在tracker服务器中,这之间的协议在后面讲客户端和tracker服务器的通信协议的时候再说。 发布者还要做的最后一件事就是将.torrent文件放在服务器上,可以通过HTTP或者FTP协议供用户下载这个.torrent文件。相比于直接将整个资源文件提供给用户下载,只传输一个.torrent文件大大降低了服务器的负荷。 这样,发布者的任务就完成了,只需要在资源传播开前保证资源服务器,也就是保存了“海贼王712集.mkv”文件的服务器在开启状态,能够持续上传直到资源传播开来。 客户端和Tracker服务器 现在我是一个动漫爱好者,我发现了漫游上有新的“海贼王712集.mkv”的BT资源,我需要怎样才能下载到这个视频呢? 首先,可以通过HTTP或者FTP协议直接从服务器上得到.torrent文件。然后使用BitTorrent软件客户端打开.torrent文件,软件会根据.torrent的name/path元信息告诉我这个.torrent文件可以下载到一个.mkv文件,一个字幕文件,在这个阶段我可以进行一些勾选,选择下载某些而不是全部的资源。 资源选择确定后,BitTorrent软件客户端就开始了下载。客户端的第一步任务根据.torrent上的URL使用HTTP GET请求,这个请求包含了很多参数,这里只介绍从客户端发送到Tracker的请求最关键的几个参数。 info_hash peer_id ip port info_hash是元信息.torrent文件中info键所对应的值的SHA1散列,可以被Tracker服务器用来索引唯一的对应资源。 peer_id是20byte的串,没有任何要求,被Tracker服务器用于记录客户端的名字。 ip可以从HTTP GET请求中直接获取,放在参数中可以解决使用代理进行HTTP GET的情况,Tracker服务器可以记录客户端的IP地址。 port客户端监听的端口号,用于接收response。一般情况下为BitTorrent协议保留的端口号是6881-6889,Tracker服务器会记录下端口号用于通知其他客户端。 在Tracker服务器收到客户端的HTTP GET请求后,会返回B encode形式的text/plain文本,同样是一个字典数据结构,其中最关键的一个键值对是peers,它的值是个字典列表结构,列表中的每一项都是如下的字典结构。 peers peer_id ip port 这些信息在每个客户端连接Tracker服务器的时候都发送过,并且被Tracker服务器保存了下来。新来的客户端自然要获取到这些下载中或者已下载完的客户端的ip,port等信息,有了这些信息,客户端就不需要像FTP或者HTTP协议一样持续找服务器获取资源,可以从这些其他客户端上请求获取资源。...

March 10, 2018 · 土川