文档章节

bt协议详解 DHT篇(上)

蓝猫163
 蓝猫163
发布于 2016/06/11 16:47
字数 2880
阅读 156
收藏 0

bt协议详解 DHT篇(上)

最近开发了一个免费教程的网站,突然产生了仔细了解bt协议的想法,这篇文章是bt协议详解系列的第三篇,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术,敬请期待。

文章主要内容来自于对DHT Protocol的翻译,如果大家感兴趣的话,可以阅读一下英文原版。

为了大家阅读的方便,把文章分成了上下篇,两篇加在一起快1w字了,确实看的比较累。

1 简介

前面讲到BT协议像tcp/ip协议一样是一个协议簇,dht协议在这个协议簇中出现的比较晚,但是它所发挥的作用却不容小视。dht协议提出的一些新的想法让我们能够推翻基础篇中的设计,得到一个更简单更高效的bt服务器和bt客户端。

在dht协议中,bt客户端使用“distributed sloppy hash table”(DHT的全称)来存储没有tracker地址的种子文件所对应的peer节点的信息,在这种情况下,每一个peer节点变成了一个tracker服务器,dht协议是在udp通信协议的基础上使用Kademila(俗称Kad算法)算法实现。

重要:注意这里使用的术语,一个peer节点是一个实现了bt协议并且开启了tcp监听端口的bt客户端或者服务器。一个node节点是一个实现了dht协议并且开启了udp监听端口的bt客户端或者服务器,这两者非常容易混淆。

dht由很多node节点以及这些node节点保存的peer地址信息组成,一个bt客户端包括了一个dht node节点,通过这些节点来和dht网络中的其它节点通信来获取peer节点的信息,然后再通过bt协议从peer节点下载文件。

看到这里大家应该明白了,dht协议并不能取代bt协议,它只是bt协议的一个强有力的补充,在一些禁止运行bt tracker服务器的国家,通过使用dht协议,用户照样可以下载想要的内容。tracker服务器本来也不保存真正的文件,只是保存和torren文件相关的peer的信息,
dht协议通过从附近的node节点获取peer信息,而不是从tracker服务器获取peer信息,这就是所谓的trackerless

2 概述

dht网络中每一个node节点有一个全局的唯一标识,叫node ID(节点id),节点id是随机从torrent种子文件中的160位的infohashes中随机抽取的。distance metric(距离度量)用来比较两个节点id或者节点id和infohash之间的距离。所有的节点(注意后面所有提到的node节点都简称节点,peer节点不作简写)必须保存一个routing table(路由表)保存它和dht网络中一小部分节点交流的信息。离节点id越近的其它节点id的信息越详细。所有的节点必须知道很多离它们很近的其它节点,离它们很远的节点只需要有足够的握手信息就行了。

在Kad算法中,距离度量是对两个hash值进行XOR(异或)运算,并且把结果转换成无符号整数。distance(A,B)=|A xor B|,结果值越小,距离越近。

当一个节点想找到一个种子文件的peer节点信息时,就使用距离算法把种子文件的infohash字段和它自己路由表中的节点id进行比较,然后和距离最近的节点进行通信,向它们发送请求获取正在下载这个种子文件的peer节点列表的信息。如果它请求的节点知道这个种子文件的peer节点列表,则把peer节点列表返回给发送请求的节点。如果不知道,它必须返回自己路由表中离infohash最近的节点列表给请求者。原始节点不断迭代的发送请求直到找到离目标infohash更近的节点。搜索结束之后,bt客户端把peer节点的信息保存在自己的路由表里面。

请求peer节点列表的返回值中包含了一个可选“token”,当一个节点声明它控制的peer节点正在下载一个种子文件时,它必须把它最近发送请求中获取的token返回向它发送请求的节点。当一个节点尝试“声明”一个种子时,被询问的节点把token和ip进行检查,这样做是为了防止冒充其它主机下载文件。因为token只是在查询节点和它获取token的节点之间发送,具体的实现没有任何限制。tokens在发布之后的一段时间之内是生效的。bittorrent客户端使用秘钥对ip进行sha1哈希,秘钥每5分钟改变一次,生成的token在10分钟内是有效的。

3 路由表

每一个节点都维护一个路由表保存一些已知的通信好的节点。路由表中的节点通常用来作为起始节点,当其它节点向这个节点发送请求时,路由表中的这些节点就会被返回给发送请求的几点。

并不是每一个已知的节点都是对等的。一些节点是活跃的(原文是“good”)的,另外一些不是。dht中的许多节点可以发送请求和接受返回,但是不会响应dht网络中其它节点的请求。每一个节点的路由表中都只保存好的节点,这一点非常重要。一个活跃的节点就是能在15分钟之内响应过请求或者在15分钟之内发送过请求的节点。15分钟之内没有活动的话,这个节点变成问题节点。当一个节点响应请求失败的话,它就变成坏的节点。活跃的节点比状态不明的节点的优先级要高(这不是显然吗?)。

路由表覆盖从0到2160完整的nodeID空间。路由表又被划分为buckets(桶),每一个bucket包含一个子部分的nodeID空间。一个空的路由表只有一个bucket,它的ID范围从min=0到max=2160。当一个nodeID为“N”的node插入到表中时,它将被放到ID范围在min< N < max的bucket中。一个空的路由表只有一个bucket所以所有的node都将被放到这个bucket中。每一个bucket最多只能保存K个nodes,当前K=8。当一个bucket放满了好的nodes之后,将不再允许新的节点加入,除非我们自身的nodeID在这个bucket的范围内。在这样的情况下,这个bucket将被分裂为2个新的buckets,每一个新桶的范围都是原来旧桶的一半。原来旧桶中的nodes将被重新分配到这两个新的buckets中。如果是一个只有一个bucket的新表,这个包含整个范围的bucket将总被分裂为2个新的buckets,第一个的覆盖范围从0..2159,第二个的范围从2159..2160

当bucket装满了好的nodes,那么新的node将被丢弃。一旦bucket中的某一个node变为了坏的node,那么我们就用新的node来替换这个坏的node。如果bucket中有在15分钟内都没有活跃过的节点,我们将这样的节点视为可疑的节点,这时我们向最久没有联系的节点发送ping。如果被pinged的节点给出了回复,那么我们向下一个可疑的节点发送ping,不断这样循环下去,直到有某一个node没有给出ping的回复,或者当前bucket中的所有nodes都是好的(也就是所有nodes都不是可疑nodes,他们在过去15分钟内都有活动)。如果bucket中的某个node没有对我们的ping给出回复,我们最好再试一次(再发送一次ping,因为这个node也许仍然是活跃的,但由于网络拥塞,所以发生了丢包现象,注意DHT的包都是UDP的),而不是立即丢弃这个node或者直接用新node来替代它。这样,我们得路由表将充满稳定的长时间在线的nodes。

每一个bucket都应该维持一个“lastchange”字段来表明bucket中的nodes有多新鲜。当一个bucket中的node被ping并给出了回复,或者一个node被加入到了bucket,或者一个node被一个新的node所替代,bucket的“lastchanged”字段都应当被更新。如果一个bucket的“lastchange”在过去的15分钟内都没有变化,那么我们将更新它。这个更新bucket操作是这样完成的:从这个bucket所覆盖的范围中随机选择一个ID,并对这个ID执行find_nodes查找操作。常常收到请求的nodes通常不需要常常更新自己的buckets,反之,不常常收到请求的nodes常常需要周期性的执行更新所有buckets的操作,这样才能保证当我们用到DHT的时候,里面有足够多的好的nodes。
在第一个node插入路由表并开始服务后,这个node应该试着查找离自身更近的node,这个查找工作是通过不断的发布find_node消息给越来越近的nodes来完成的,当不能找到更近的节点时,这个扩散工作就结束了。路由表应当被启动工作和客户端软件保存(也就是启动的时候从客户端中读取路由表信息,结束的时候客户端软件记录到文件中)。

4 bt协议扩展

BitTorrent协议已经被扩展为可以在通过tracker得到的peer之间互相交换nodeUDP端口号(也就是告诉对方我们的DHT服务端口号),在这样的方式下,客户端可以通过下载普通的种子文件来自动扩展DHT路由表。新安装的客户端第一次试着下载一个无tracker的种子时,它的路由表中将没有任何nodes,这是它需要在torrent文件中找到联系信息。

peers如果支持DHT协议就将BitTorrent协议握手消息的保留位的第八字节的最后一位置为1。这时如果peer收到一个handshake表明对方支持DHT协议,就应该发送PORT消息。它由字节0x09开始,payload的长度是2个字节,包含了这个peer的DHT服务使用的网络字节序的UDP端口号。当peer收到这样的消息是应当向对方的IP和消息中指定的端口号的node发送ping。如果收到了ping的回复,那么应当使用上述的方法将新node的联系信息加入到路由表中。

本文来自 免费教程网

© 著作权归作者所有

共有 人打赏支持
蓝猫163
粉丝 10
博文 14
码字总数 20906
作品 1
广州
程序员
一步一步教你写BT种子嗅探器-原理篇

之前看到 lantern 这个十分火的翻墙工具,其利用了P2P的思想,就想了解一下P2P相关的协议。看了下最流行的BT协议官方文档,就产生了实现BT协议的想法,顺便根据协议实现了一个BT种子嗅探器。...

lime66
2016/08/10
1K
2
一步一步教你写BT种子嗅探器--DHT篇

之前写了原理篇,在原理篇里简单的介绍了一下DHT,但是还不够详细。今天我们就专门详细的讲一下嗅探器的核心-DHT,这里默认原理篇你已经读了。 背景知识 DHT全称 Distributed Hash Table,中...

lime66
2016/08/13
2.2K
0
你写过 Web 爬虫, 那么你写过 P2P 爬虫吗?

网络爬虫爱好者为了爬取视频, 图片, 文档, 软件, 可能只想到写一个 Web 爬虫, 从各大网站爬取. 但是你知道吗? 这个世界上, 还有 DHT 协议, BitTorrent 协议. 想想看, 全世界每天有那么多人通...

CrazySpiderMan
2016/03/03
2.1K
13
BTG

BTG是一款采用C++和Libtorrent库开发的,基于GPL协议发布的linux下BT客户端软件。这款BT工具的最大特色就是可以分别基于 Ncurses、Gtkmm和www GUI三种前端对处于后台的BT实体下载后端进行操作...

匿名
2008/11/15
1K
0
uTorrent 1.8.5 RC1

uTorrent是一款小巧的BT客户端程序,拥有常见的功能.内网下载方面也有不错的表现,外网就更不用提了.支持多任务同时下载,支持设置文件 下载优先级,可以根据计划任务调整占用的带宽,全局/单个任...

红薯
2009/10/25
427
0

没有更多内容

加载失败,请刷新页面

加载更多

腾讯投资最高1.75亿美元正式进军菲律宾移动支付市场

菲律宾长途电话公司(PLDT)公司今日宣布,中国互联网巨头腾讯和私募股权公司KKR将获得该公司旗下金融科技公司Voyager Innovations的少数股权。 PLDT在一份声明中称:“腾讯和KKR最多将分别收...

linuxCool
28分钟前
2
0
正则介绍及grep/egrep用法

10月16日任务 9.1 正则介绍_grep上 9.2 grep中 9.3 grep下 扩展 把一个目录下,过滤所有*.php文档中含有eval的行 grep -r --include="*.php" 'eval' /data 正则介绍 正则就是一串有规律的字符...

hhpuppy
39分钟前
1
0
J2Cache 中使用 Lettuce 替代 Jedis 管理 Redis 连接

一直以来 J2Cache 都是使用 Jedis 连接 Redis 服务的。Jedis 是一个很老牌的 Redis 的 Java 开发包,使用很稳定,作者维护很勤勉,社区上能搜到的文章也非常非常多。算是使用范围最广的 Redi...

红薯
今天
13
0
一个可能的NEO链上安全随机数解决方案

0x00 困境 链上安全随机数生成应该算是一个比较蛋疼的问题,哪怕你的系统再牛逼,合约程序困在小小的虚拟机里,哪怕天大的本事也施展不开。 更悲催的是,交易执行的时候,是在每一个节点都执...

暖冰
今天
1
0
【大福利】极客时间专栏返现二维码大汇总

我已经购买了如下专栏,大家通过我的二维码你可以获得一定额度的返现! 然后,再给大家来个福利,只要你通过我的二维码购买,并且关注了【飞鱼说编程】公众号,可以加我微信或者私聊我,我再...

飞鱼说编程
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部