学习笔记:P2P网络

发布于 2018-01-20  8,409 次阅读


今天闲来无事,花了大半天的时间来研究了一下P2P网络究竟是怎么一回事,这篇文章的性质为学习笔记,林和并不能保证文章中的内容绝对准确。
(本文中的P2P,指的是peer to peer,即对等网络)

原理概述

//参考了有关此条目的维基百科英文页面

P2P网络/P2P计算是指依托于用户群(peers)分担的工作负载而构建起来的分布式结构,所有用户之间是对等的,装备了用于参与网络的应用程序。用户使它们自己拥有的资源中的一部分,例如计算能力,磁盘储存或者网络流量对网络中的别的用户来说直接可用,而不需要借助中心化的服务器的协调。所有的用户既是资源的提供者也是使用者,这一点区别于服务器-客户端模式中的资源的使用的提供方式。

结构

P2P网络依靠建立在实际的物理意义上的网络连接以上的覆盖网络实现,覆盖网络的节点构成了实际网络的一个子集。数据实际上还是通过底层的TCP/IP协议传输,但是在应用层面上,P2P网络中的成员可以通过“逻辑”上的连接直接沟通。覆盖网络被用来进行用户的索引和发现,这是P2P网络不同于物理网络连接的地方。根据覆盖网络中的节点如何连接,资源如何索引和定位,P2P网络可分为两种。

(以下几个名词也许与别处的中文翻译有出入)

非结构化网络

非结构化网络并非是经过设计而形成的网络结构,而是由节点之间随机地连接而形成的。由于非结构化网络本身没有结构,所以它非常容易建立并且易于针对覆盖网络中的不同地区进行本地优化。由于所有节点扮演着相同的角色,非结构化网络在面对有大量用户频繁加入和离开P2P网络的情况时非常强大。

然而,非结构化网络最大的缺点也在于没有结构。举例来讲,当某用户希望在这个P2P网络中寻找他想找的资源,那么搜索请求需要进行广播,然后遍历网络中的所有用户,尽可能多得发现分享了这份资源的用户。然而这样的遍历就会带来问题:引起网络中出现大量作为信号的流量,占用较多的CPU/内存资源,而且没办法保证这些搜索请求一定能被正确解析(响应)。进一步地,由于没有校验的机制,无法保证这样的网络之中可以找到期望的数据。流行的内容可能在若干节点中都可用,这样一来几乎所有的用户在不同的节点之中找到的都是一样的资源,而当用户想找冷门资源的时候很有可能就找不到东西了。

 

老司机们你们熟悉的东西来了!!

结构化网络

在结构化网络之中,覆盖层以一种特别的拓扑结构组织起来,这种协议保证节点可以在网络中高效地搜索文件/资源,即使这种资源在这个网络之中非常稀有。

结构化P2P网络常用的一种类型是 分布式散列表/分布式哈希表 (DHT,distributed hash table)。要谈“分布式”的散列表,要先明白什么是“散列表”。

散列表/哈希表用来储存键值对(Key/Value pairs),不严谨的说,key相当于一个索引,value相当于内容本身。我们要确定这个文件是不是我们需要的那个文件,就需要进行完整性校验,当然,这一步可以把所有数据一点一点比对,但那是一种非常低效的办法,而且常常无法在实际中应用。散列可以加速这个比较过程,我们利用“某种算法”,根据一个很长的文件,算出一个长度固定且较短的数字,把这个数字作为“索引”,当两个文件经过散列函数得到的值相同时,可以判定这两个文件在很大可能上是相同的。当然了,知道抽屉原理的人都知道,把长度长的文件算出一个较短的值,必然会有两个或多个文件得到相同的值,这称为散列冲突(hash collision)。所以我们需要这个散列函数足够的“分散”,尽可能地降低冲突的情形。

老司机们注意啦,你们开车的时候常常看到的磁力链接后面长长的一串字符其实就是你们找的豪车的十六进制散列值。

而散列表,就是储存了这种对应关系的数据结构。我知道了一个散列值,即键值对中的键,拿着这个键就可以找到我要找的值所储存的位置,这样就完成了快速查找。(这种方法可以应用于内存)所谓分布式,是指传统的散列表是储存在单机中的,而分布式,即是把这个表分开储存在各个节点之中,每个节点不必知道网络中全部内容所有的哈希值,而只需要储存其中(往往是很小的)一部分,而遇到本机储存的哈希表中没有的哈希值时,就根据已经构建好的“某种结构”,按照“某种方式”(这些结构和方式都是为了尽可能快而设计的)去向网络中与它相连的计算姬查询。这样,只要某台计算姬连接上了一台处于P2P网络中的计算姬,它就可以连接上整个P2P网络中的资源。

当然,从上面的介绍就看得出来,要接入一个DHT网络,首要条件就是连接上一台已经在组织中的设备。当然实际情形中不会只依赖一种办法来进行节点发现,会一起使用多种办法。

举几个栗子

追踪服务器

打开一个BT下载工具,utorrent,bittorrent什么的都行,可以看到

这个trackers就是用来进行节点发现的。因为P2P网络是一个覆盖网络,实际上的通信还是要依靠物理上的网络,那么在通信时首先需要解决的问题就是,在物理网络中哪些计算机处于P2P网络之中,会响应我的请求,这就是节点发现。tracker服务器就相当于中介,在有的软件本身会内置一些追踪服务器的IP与端口,例如Resilio Sync(原Bittorrent Sync)的软件需要先和官方服务器沟通一次才能正常使用。但是,这个官方中介的IP和端口一般都是固定的,P2P本身分布式的网络设计就追求分布式,去中心化,搞官方中介其实又在实际中弄出了一个类似中心的东西,如果有人想攻击这个P2P网络,只需要把这个官方中介搞垮或屏蔽就OK了。

DHT网络

刚才已经介绍过了,在DHT网络中,你只需要抓到一只没掉队的计算姬就可以找到组织,然而这恰恰是实际中最为困难的一件事,就像是先有鸡还是先有蛋的问题一样:我必须先找到一个节点,才能找到查询节点位置的办法。在缺少trackers server(追踪服务器)的情况下,就算有DHT网络,掉了队的计算姬依然找不到回组织的路。。。

预定义主机(predefined hosts)

如果用Resilio Sync 的话,就会发现它的设置中有一项预定义主机,指的是如果我可以确认某只计算姬一定处于P2P网络之中,我就先去撩她~

咳咳。。。

这种方法应用场景很受限,在常规情况下几乎不会用到,,但是在某些特别情况下还是很管用的。没错,当你有一台VPS的时候,VPS可以作为预定义主机。这样的操作也成为了解决自2017年7月以来btsync被GFW干扰的方法之一。

 

 

接下来我想写两篇文章,一篇用来介绍同步神器Resilio Sync(原btsync),另一篇来详细探讨“某种结构”和“某种方法”的细节。


终有一日, 仰望星空