一、文件共享网络

第一代

中央服务器。以文件服务器作为中心,典型的提供FTP的服务器。这种方式对服务器带宽压力和机器性能压力巨大。而且,这种单点集权的模式风险非常大,一旦出现故障,整个服务将停止。

第二代

泛洪式查询。网络中每一个节点都向他邻居节点询问是否拥有资源,如果没有,邻居继续向他的邻居询问。这种广播式的查询缺点明显,每次向外传播都是指数级,很容易就形成蝴蝶效应般的影响,对网络资源消耗非常大,而且容易形成网络风暴。以至于要对广播的广度和深度进行限制。

典型的例子是Gnutella,2000年的一种文件共享网络。广播广度被限制在5个邻居,深度不大于7跳。但5^7=78125这个数量也是很惊人。尽管它没有直接查询中心节点有效率,但它不再依赖一个中心化的索引节点。

第三代

BTtorrent-tracker。BT的网络架构中存在一个中心服务器Tracker,用来保存BT网络巾各节点的IP地址和端口等信息。下载节点刚加入网络时从Trakcer上获得其他节点的地址信息,同时在tracker中注册自己的信息成为一个peer。实现一个节点同时与多个节点交互。

第四代

Bttorrent-DHT。虽然第三代文件共享网络实现了P2P,但也有个缺点,如果tracker被屏蔽或者被黑,那么新节点无法注册,也无法获得peer列表,整个P2P网络就瘫痪。DHT(分布式哈希表)网络的出现,作为BT协议强而有力的拓展,解决了以上问题。

DHT全称 Distributed Hash Table,中文翻译分布式哈希表。它是一种去中心化的分布式系统,特点主要有自动去中心化,强大的容错能力,支持扩展。另外它规定了自己的架构,包括keyspace和overlay network(覆盖网络)两部分。但是他没有规定具体的算法细节,所以出现了很多不同的实现方式,比如Chord,Pastry,Kademlia等。BitTorrent中的DHT是基于Kademlia的一种变形。本文也是根据Kademlia协议描述DHT网络。

二、相关名词

peer:一个实现了BT协议并且开启了tcp监听端口的bt客户端或者服务器

node:一个实现了DHT协议并且开启了udp监听端口的bt客户端或者服务器

tracker:最终指引请求者找到目标peer的主机。在DHT网络中,存储了peer信息的node充当一个虚拟tracker的角色。

info_hash:一个由40位16进制数字组成的字符串,总共有160bit。由SHA-1计算torrent文件中的info得出的作为资源的唯一标识。

B编码(Bencode编码):一种torrent文件信息存储格式

哈希表:也称散列表。根据关键码值(Key value)而直接进行访问的数据结构。这个映射函数叫哈希函数,存放记录的数组叫哈希表。

三、Kademlia协议(简称 Kad)

1.两个关键的id:

nodeid,节点id。节点包含了网络ip地址和端口号,由唯一的节点id指向这一个节点。节点id为160位的二进制表示。

key。网络中的资源名索引和资源名以key-value键值对的形式表示,资源名经过哈希函数计算,转为160位的key。

2.异或距离:

由上述的两个id,把资源放置在nodeid与key的距离相近的节点上,就能实现资源的定位。也就是我们可以根据key去匹配距离相近的nodeid,然后找到在该节点上与key对应的资源value。

其中的距离指的是异或距离。也就是对两个id进行异或运算,可以是nodeid与nodeid,定位节点。或者nodeid与key,定位资源。

举个例子:00110 与 00011 的异或距离为 00101,也就是5。(0⊕0=0,1⊕0=1,1⊕1=0)

3.异或特性:

x ⊕ x = 0,节点与它本身的异或距离为0。

x ⊕ y > 0 , if x != y,不同节点异或距离一定大于0。

x ⊕ y =  y ⊕ x,异或距离是对称的。

x ⊕ y + y ⊕ z >=  x ⊕ z,类似于三角形不等式,第三边的距离小于等于另外两边的距离之和。

x ⊕ y ⊕ y ⊕ z =  x ⊕ z

x + y >= x ⊕ y

4.路由表,与k-bucket:

由于节点id是一串二进制数,每一位的取值只有0或1,因此我们可以把节点id表示为二叉树的形式。以100为例,第一位是1,(从上到下)往右子树,第二位是0,往左子树,第三位是0,再往左子树。最终的叶子节点即为100。类似于文件夹的路径。

k-bucket

k-buckst树形结构

我们把同一个灰色部分的节点放置在同一个列表,这个列表称为k-bucket,k桶。k桶中的k指的是每一个列表所能容纳的节点的最大个数。

划分k桶是有规律的。k桶的个数跟节点id的位数有关,假设节点id的位数为n,则最多有n个k桶。第1个k桶中的节点与本地节点前n-1位id是相同,第2个k桶中的节点与本地节点前n-2位id是相同,以此类推,最后第n个k桶中的节点与本地节点第1位id就不一样了。

所有的k桶合起来也就是一个节点的路由表。

这里以nodeid为110的节点为例,共有3个k桶。第i个k桶中异或距离的范围为[2^i,2^(i+1))。

可以类比为国家的行政区域划分来理解。

节点距离

节点id为110的路由表

5.协议消息:

PING — 验证远程节点是否在线。

STORE — 在某个节点上存储 key-value 键值对。在节点上存储资源。

FIND_NODE — 查找节点,给定一个nodeid,被请求的节点返回与nodeid相近的k个节点。

FIND_VALUE — 查找资源,给定一个key,被请求的节点的nodeid与key相近,并且具有该key,返回与key对应的value。

四、BitTorrent基于Kad协议的实现

KRPC协议

KRPC是BitTorrent在Kademlia理论基础之上定义的一个通信消息格式协议,是由B编码组成的一个简单的RPC结构,有4种请求:ping、find_node、get_peers 和 announce_peer。一条 KRPC 消息即可能是request,也可能是response

KRPC字典基本组成元素

1. t关键字: 每条消息都包含 t 关键字,它是一个代表了 transaction ID 的字符串。transaction ID 由请求节点产生,并且回复中要包含回显该字段(挑战-响应模型),所以回复可能对应一个节点的多个请求。transaction ID 应当被编码为一个短的二进制字符串,比如 2 个字节,这样就可以对应 2^16 个请求

2. y关键字: 它由一个字节组成,表明这个消息的类型。y 对应的值有三种情况

1) q 表示请求(请求Queries): q类型的消息它包含 2 个附加的关键字 q 和 a

1.1) 关键字 q: 是字符串类型,包含了请求的方法名字(get_peers/announce_peer/ping/find_node)

1.2) 关键字 a: 一个字典类型包含了请求所附加的参数(info_hash/id..)

2) r 表示回复(回复 Responses): 包含了返回的值。发送回复消息是在正确解析了请求消息的基础上完成的,包含了一个附加的关键字 r。关键字 r 是字典类型

2.1) id: 当前节点id,peer节点id号或者下一跳DHT节点

2.2) nodes: ""

2.3) token: token

3) e 表示错误(错误 Errors): 包含一个附加的关键字 e,关键字 e 是列表类型

3.1) 第一个元素是数字类型,表明了错误码,当一个请求不能解析或出错时,错误包将被发送。下表描述了可能出现的错误码

201: 一般错误

202: 服务错误

203: 协议错误,比如不规范的包,无效的参数,或者错误的 toke

204: 未知方法

3.2) 第二个元素是字符串类型,表明了错误信息

ping报文

检测节点是否可达,请求包含一个参数id,代表该节点的nodeID。对应的回复也应该包含回复者的nodeID

ping Query = {"t":"aa","y":"q","q":"ping","a":{"id":"abcdefghij0123456789"}}

bencoded = d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe

Response = {"t":"aa","y":"r","r": {"id":"mnopqrstuvwxyz123456"}}

bencoded = d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re

find_node报文

find_node 被用来查找给定 ID 的DHT节点的联系信息,该请求包含两个参数id(代表该节点的nodeID)和target。回复中应该包含被请求节点的路由表中距离target最接近的K个nodeID以及对应的nodeINFO。应用在定位node的位置,初始化或更新自己的K桶列表。

find_node 请求包含 2 个参数,第一个参数是 id,包含了请求节点的ID。第二个参数是 target,包含了请求者正在查找的节点的 ID

当一个节点接收到了 find_node 的请求,他应该给出对应的回复,回复中包含 2 个关键字 id(被请求节点的id) 和 nodes,nodes 是字符串类型,包含了被请求节点的路由表中最接近目标节点的 K(8) 个最接近的节点的联系信息(被请求方每次都统一返回最靠近目标节点的节点列表K捅)

find_node Query = {"t":"aa","y":"q","q":"find_node","a": {"id":"abcdefghij0123456789","target":"mnopqrstuvwxyz123456"}}

# "id"containing the node ID of the querying node, and"target" containing the ID of the node sought by the queryer.

bencoded = d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe

Response = {"t":"aa","y":"r","r": {"id":"0123456789abcdefghij","nodes":"def456..."}}

bencoded = d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re

get_peers报文(相当于find_value)

1.get_peers 请求包含2 个参数(id请求节点ID,info_hash代表torrent文件的infohash,infohash为种子文件的SHA1哈希值,也就是磁力链接的btih值)

2. response get_peer:

1) 如果被请求的节点有对应 info_hash 的 peers,他将返回一个关键字 values,这是一个列表类型的字符串。每一个字符串包含了"nodeid-ip-port"格式的 peers 信息。关键字 token 都将被返回。token 关键字在今后的 annouce_peer 请求中必须要携带。

2) 如果被请求的节点没有这个 info_hash 的 peers,那么他将返回关键字 nodes,这个关键字包含了被请求节点的路由表中离 info_hash 最近的 K 个节点(我这里没有该节点,去别的节点试试运气)。

announce_peer 报文(相当于store)

announce_peer: 这个请求用来表明发出 announce_peer 请求的节点,正在某个端口下载 torrent 文件

announce_peer 包含 4 个参数

1. 第一个参数是 id: 包含了请求节点的 ID

2. 第二个参数是 info_hash: 包含了 torrent 文件的 infohash

3. 第三个参数是 port: 包含了整型的端口号,表明 peer 在哪个端口下载

4. 第四个参数数是 token: 这是在之前的 get_peers 请求中收到的回复中包含的。收到 announce_peer 请求的节点必须检查这个 token 与之前我们回复给这个节点 get_peers 的 token 是否相同(也就说,所有下载者/发布者都要参与检测新加入的发布者是否伪造了该资源)

如果相同,那么被请求的节点将记录发送 announce_peer 节点的 IP 和请求中包含的 port 端口号在 peer 联系信息中对应的 infohash 下,这意味着一个一个事实: 当前这个资源有一个新的peer提供者了,下一次有其他节点希望或者这个资源的时候,会把这个新的(前一次请求下载资源的节点)也当作一个peer返回给请求者,这样,资源的提供者就越来越多,资源共享速度就越来越快。

一个peer正在下载某个资源,意味着该peer有能够访问到该资源的渠道,且该peer本地是有这份资源的全部或部分拷贝的,它需要向DHT网络广播announce消息,告诉其他节点这个资源的下载地址

五、DHT网络的其他应用

1、以太坊

2、洋葱网络

六、一些数字比较

为了让大家能更直观的了解DHT网络的节点空间容量,我翻了一些数据作为比较。

1、DHT网络有160bit,可以容纳2^160个节点,也就约等于 10^48个节点。

2、地球的总人数70亿,四舍五入100亿(10^10)

3、原子核直径10^-14米。

4、银河系最长直径1.7029e+21米。本星系群9.4607e+22米 。室女座超星系团 9.4607e+23(约10^24)米。

那么假如每个人都成为DHT网络中的节点,就只占据整个网络的 10^38分之一;这个尺度就相当于一颗原子核相对于室女座超星系团那么大。哈希碰撞基本不用考虑。

但神奇的是,在那么大的网络中,寻找其中任意一点,最多只需要160次find_node就可以完成。这与六度人脉理论异曲同工。

七、留下思考问题

为什么BT协议实现DHT网络要用二叉树呢?如果用16叉树会怎样?

参考资料

dht网络协议 服务器,概述DHT网络相关推荐

  1. NTP网络时钟服务器(ntp网络同步时钟)在某空管局案例分析

    NTP网络时钟服务器(ntp网络同步时钟)在某空管局案例分析 NTP网络时钟服务器(ntp网络同步时钟)在某空管局案例分析 本文由安徽京准公司提供请勿转载! 2019年3月,安徽京准电钟自主研发生产的 ...

  2. 服务器网络协议是什么,介绍网络协议,什么是网络协议三要素?

    网络的复杂性取决于人们对它的需求.那么在这当中,最为重要的就是网络协议了.那么什么是网络协议?相信很多人都会疑惑,下面给大家介绍网络协议是什么以及网络协议的三要素是什么的基础知识,不懂的朋友可以通过本 ...

  3. internet协议服务器在哪,网络协议在哪设置

    互联网是对全世界都开放的网络,任何单位或个人都可以在网上方便地传输和获取各种信息,互联网这种具有开放性.共享性.国际性的特点就对计算机网络安全提出了挑战.网络协议在哪设置?计算机网络安全有哪些基本注意 ...

  4. 趣谈网络协议-第二模块-底层网络知识详解:4陌生的数据中心2CDN和数据中心

    趣谈网络协议-第二模块-底层网络知识详解:4陌生的数据中心2CDN和数据中心 1:CDN:你去小卖部取过快递么? 使用"中间仓库"来优化 网络中的"就近配送" ...

  5. ip广播系统服务器软件,【网络广播服务器软件IP网络广播软件数字广播软件】 - 太平洋安防网...

    [参数说明] 品牌:万凯wankai [详细描述] ★具备*版权局颁发的计算机软件**:                                                         ...

  6. 趣谈网络协议-第二模块-底层网络知识详解:2最重要的传输层

    趣谈网络协议-第二模块-底层网络知识详解:2最重要的传输层 1:第10讲 | UDP协议:因性善而简单,难免碰到"城会玩" TCP 和 UDP 有哪些区别? UDP 包头是什么样的 ...

  7. java相关网络协议无响应_java网络协议有哪些

    上网的途径有很多,java是最普遍的,那么卑java网络协议有哪些?了解网络安全常识,首先就要了解计算机网络安全有哪些基本注意事项,下面佰佰安全网小编就带您认识一下吧. 概念 协议是指计算机通信网络中 ...

  8. 怎么在win7链接无线网络连接服务器,Win7系统网络连接一直显示正在获取网络地址但是连不上网解决方法...

    电脑上不了网的原因很多,比如是网络设置问题.路由器问题.运营商问题.最近一个Win7用户,网络连接一直显示,正在获取网络地址但是连不上网,但是其它电脑可以上网,那么说明是电脑设置问题,那么该如何解决呢 ...

  9. java常用网络协议_初识java网络编程

    一.基本概念什么是计算机网络?计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递 ...

  10. 网络协议和浏览器到网络简单攻防实现的探索(二)

    一.关于网络协议的整体梳理 1.1 客户端和服务端的通信 常见的架构,B/S和C/s架构.而在浏览器中运行王爷的属于B/S架构.网页浏览器通过地址栏的url获取服务器对应的资源文件.通过浏览器的处理后 ...

最新文章

  1. python写入txt文件正常,但是写入csv文件中文乱码问题
  2. Scapy 伪造网络数据包
  3. ORACLE相关的SHELL编程
  4. 这是私人的事,法官大人
  5. 华为路由器配置OSPF实例
  6. 二级索引 -> 普通索引 与 唯一索引
  7. 无标号有根树计数与无标号无根树计数
  8. 5G核心网中与用户数据相关的NF功能体UDM、AUSF、PCF、UDR
  9. c语言布丰投针源码,布丰投针数学分析及实验设计(原创).pdf
  10. Ignoring invalid timezone passed to Connection
  11. tomcat修改主页
  12. “应用程序无响应”原因汇总
  13. 如何使用Windows10自带的photo应用给视频添加字幕
  14. HTTPS加密网站,地址重写配置
  15. 移动端测试介绍和练习
  16. NodeJS使用socket传输大文件
  17. 基于MATLAB的DTMF信号的仿真分析
  18. 计算机课件制作软件,浅谈计算机课件制作
  19. 方法模板ThinkPHP3.1.2项目技巧三部曲 一
  20. varbinary转换成字符串

热门文章

  1. LabVIEW安装多个NI软件产品时的安装顺序
  2. c语言抽签系统_抽签小程序(C语言随机数)
  3. postgresql 身份证、手机号、营业执照验证脚本
  4. .net pc微信扫码登录
  5. Scala3下载及安装下载地址(Mac安装Scala)
  6. Kettle Spoon 安装配置详解
  7. 笔记:linux中tcp_tw_reuse和tcp_tw_recycle的作用
  8. Python人脸识别考勤打卡系统
  9. 惠普局域网共享打印机设置_已解决: hp1106局域网共享打印机共享 - 惠普支持社区 - 817337...
  10. 如何解决使用PCS7时报警无法确认的问题?