1、P2P技术简介
P2P,即peers-to-peers,是一种点对点的通信模式。它不同于C/S模式,即不需要一个中心服务器来完成各种网络应用;它是一个分布式网络,网络中的任何节点既可以是服务器,也可以是客户端,所有节点的地位都是平等的。
P2P网络拓扑模式的发展主要经过了三个阶段:集中式P2P、分布式P2P和混合式P2P。
集中式是最早期的P2P网络结构,网络中需要一个中心服务器。中心服务器用于记录各个对等节点的共享资源信息,并响应对等节点生成共享资源的索引信息。当一个节点请求一个未知位置的资源时,首先会查询中心服务器;中心服务器检索自己的数据库,找到匹配该资源信息的定位信息,返回给查询的节点;然后该节点直接与拥有该共享资源的节点进行交互。集中式的优点是查询资源所在位置迅速方便,但要完全依赖于中心服务器,中心服务器宕掉时,整个网络就会瘫痪。
分布式P2P网络中不存在中心服务器,各节点随机接入到网络中。当某节点请求一个未知位置的资源时,会以洪泛、随机漫步、选择转发等方式搜索网络资源。这种方式不必依赖于服务器来检索信息,避免了单点失效的问题;但由于检索数据包会遍历整个网络,使网络上会存在大量的无用数据包而占用大量的带宽,网络开销比较大。
混全式P2P综合了集中式和分布式的优点,网络的节点按性能划分为普通节点与超级节点,若干普通节点以一个超级节点为中心形成一个类似于集中式P2P的小型网络,而各小型网络又通过超级节点相连形成一个大的网络。各超级节点用于记录其管辖范围内普通节点的共享资源信息,并响应普通节点生成共享资源的索引信息。当一个普通节点请求一个未知位置的资源时,首先查询与之相连的超级节点;若该超级节点搜索到该资源的拥有者,则直接返回该资源的拥有者信息;若该超级节点中无匹配资源的信息时,则将请求查询包发送给与自己相邻的超级节点。
目前主要是使用混合式P2P网络拓扑结构。
2、BitTorrent*载下**原理
2.1、BitTorrent*载下**原理概述
BitTorrent是一款比较典型的P2P*载下**软件。用BT*载下**有一个优点,就是用户越多,*载下**速度反而越快。它的工作原理图如下所示:

图1 BT*载下**示意图
甲将文件成功上传到Tracker伺服器后,便成为了一个种子,他可以到各大BT论坛或网站去发布这个.torrent文件。乙和丙点击这个.torrent文件后就连上了Tracker;Tracker会根据.torrent文件中包含的信息将甲的IP地址告知乙丙两人。连接到甲后,乙随机*载下**文件的A部分,丙随机*载下**B部分,此时Tracker会记录下有乙丙两用户在*载下**文件。当乙和丙*载下**完各自的那部分后,Tracker会告诉他们其他正在*载下**的用户地址,这样乙找到了丙,并*载下**丙的B部分,同时乙继续从甲那里*载下**文件的C部分。*载下**完成后,只要不关闭BT客户端,乙将自动成为一个种子,同时乙的IP会加入到服务器的列表中。这样,每台电脑既是客户端又是服务器,在有效减轻服务器负担的基础上充分利用了上行带宽资源,所以同时间*载下**的人越多,*载下**速度越快。
2.1.1、种子
我们常说的"种子",即一个.torrent文本文件,我们用记事本打开,可以清楚地看到,种子文件中首先包含了announce URL,即tracker的位置;接着是一些文件信息,包括文件名、目录名、长度等;最后是块长度和块的Sha1校验码。它的主要原理是需要把提供*载下**的文件虚拟分成大小相等的块,并把每个块的索引信息和验证码写入.torrent文件中;所以.torrent文件就是被*载下**文件的索引。

图2 BT‘种子’例图
例如上面这个.torrent文件,打开后,我们可以得到*载下**该资源需要用到的tracker服务器的地址为http://hdroad.org/announce.php?passkey=66abdd3a50b759d797cc00220e8ccf487。
*载下**时,BT客户端首先解析.torrent文件得到Tracker地址,然后连接Tracker服务器。Tracker服务器回应*载下**者的请求,提供*载下**者其他*载下**者(包括发布者)的IP。*载下**者再连接其他*载下**者,根据.torrent文件,两者分别向对方告知自己已经有的块,然后交换对方没有的数据。*载下**者每得到一个块,需要算出*载下**块的验证码与.torrent文件中的对比,如果一样则说明块正确,不一样则需要重新*载下**这个块。
2.2、BitTorrent工作流程分析
我们使用BitTorrent7.2.1,对其启动和*载下**过程进行数据包捕获,大体分析了BitTorrent的工作流程。
2.2.1、BitTorrent启动过程
BitTorrent客户端软件启动时会与BitTorrent相关网络服务器进行交互。客户端最开始接入BitTorrent平台所采用的形式是首先通过DNS对各网络服务器的域名进行查询,获得它们的IP地址,然后通过这个地址和BitTorrent平台建立最初的联系;联系会使用HTTP GET报文和TCP、UDP报文,以获得BitTorrent界面上显示的这些内容。

图3 BitTorrent软件
通过使用wireshark对客户端软件的启动过程进行抓包,可以得到BitTorrent相关网络服务器的域名(IP地址)如下:
www.bittorrent.com:bittorrent主页,也作为搜索提供者。客户端软件启动时会使用HTTP GET请求来获得相关的bittorrent站点。
apps.bittorrent.com:BitTorrent的应用软件服务器,存放着其旗下的一些应用软件。在客户端启动时与之通过TCP三次握手建立连接,使用HTTP GET报文和TCP报文来请求软件存储资源并得到这些软件的列表,对应于BitTorrent客户端软件的下列版块:
update.bittorrent.com:BitTorrent的升级服务器。在客户端启动时会自动检查版本更新;该过程是通过HTTP的GET请求来实现的。
router.bittorrent.com:DHT网络服务器(DHT,即分布式哈希表,是类似tracker的根据种子特征码返回种子信息的网络)。若客户端软件设置了启用DHT网络,启动时会与DHT服务器的6881端口建立起UDP连接;当tracker服务器宕掉时或被禁掉时,用户可以作为一个DHT网络节点,来*载下**其他节点上的资源。
google.com:搜索提供者。在客户端软件启动时,连接到服务器后会发送一个HTTP GET请求,请求URI为/favicon.ico。
www.google.com搜索提供者。在客户端软件启动时,连接到服务器后会发送一个HTTP GET请求,请求URI为/favicon.ico。
search.vuze.com:搜索提供者。在客户端软件启动时,连接到服务器后会发送一个HTTP GET请求,请求URI为/favicon.ico。
www.mininova.org:搜索提供者。在客户端软件启动时,连接到服务器后会发送一个HTTP GET请求,请求URI为/favicon.ico。
测试时我们搭建环境使客户端PC访问外网的流量都穿过防火墙设备,在设备上配置了访问控制策略,分别测试目的为各网络服务器IP地址的策略动作为禁止时的BitTorrent*载下**软件启动情况,可以大体知到各服务器的功能,如上所述。
2.2.2、BT*载下**与上传过程
之前说过,在种子中包含着Tracker伺服务器的地址。当我们点击2.1.1中示例的.torrent文件*载下**时,首先客户端会解析这个种子文件,得到Tracker的域名为hdroad.org;然后通过DNS域名解析得到Tracker伺服器的IP地址如下图112.65.216.4,如下所示:

图4 DNS解析

图5 Tracker伺服器抓包
之后,客户端会开启任一TCP端口与Tracker的80端口通过TCP三次握手建立连接,然后通过HTTP GET向Tracker请求获得该文件的上传者列表,如下所示:
在这里,passkey是.torrent文件给出的,使用私有tracker伺服器必须要有passkey;info_hash是.torrent文件中info部分的Sha1校验码,Tracker通过它在发布列表中找到对应的记录;peer_id是自身的标识;port是自身提供上传的UDP端口,该版本的BitTorrent可以随机设置;uploaded和downloaded分别表示自己已上传了多少和*载下**了多少;left表示还有多少字节未*载下**;event是告诉伺服器日准备开始*载下**,还是停止*载下**还是完成了。
Tracker收到请求后,用info_hash这一串代码来查询发布列表,然后返回正*载下**和拥有该文件的用户IP和PORT等,如下所示:

图6 Tracker查询发布列表代码
Interval是Tracker告知客户端每隔多长时间查询一次,这里是1080s;后面是该文件拥有者的信息,在这里是经过编码了的。
同时,Tracker会将我们提供的IP和PORT放到info_hash对应的列表中,在其他用户*载下**该文件时,我们自身也会为其他用户提供*载下**资源。
客户端得到了其他peers的信息后,便会自动连接到这些用户,去*载下**这些用户已有的而自己没有的块。
*载下**使用UDP协议或TCP协议,报文如下所示:

图7 udp*载下**流

图8 tcp*载下**流
当然,我们在*载下**资源的同时,也可能会向这些用户上传我们已有的而他们还未*载下**到的块。*载下**的速度和上传的速度是成正比的,所以我们若想使*载下**速度更块,就不能吝啬我们上传的速度,即体现了一种"人人为我,我为人人"的思想。
2.2.3、续传
当我们使用BitTorrent客户端打开.torrent文件后,首先要选择文件的保存路径。若该目录下文件不存在,就建立新文件;若存在,就用 Sha1 校验码去校验文件,错误的就是还没有*载下**的。这样,就可以连接其他peers去*载下**自己没有的部分,实现文件的续传。