bt协议详解 DHT篇(上)
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的联系信息加入到路由表中。
本文来自 免费教程网
bt协议详解 DHT篇(上)的更多相关文章
- bt协议详解 DHT篇(下)
bt协议详解 DHT篇(下) 最近开发了一个免费教程的网站,产生了仔细了解bt协议的想法,这篇文章是bt协议详解系列的第三篇,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术 ...
- bt协议详解 基础篇(上)
bt协议详解 基础篇(上) 最近开发了一个免费教程的网站,产生了仔细了解bt协议的想法,所以写了这一篇文章,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术,敬请期待. 1 ...
- bt协议详解 基础篇(下)
bt协议详解 基础篇(下) 最近开发了一个免费教程的网站,产生了仔细了解bt协议的想法,所以写了这一篇文章,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术,敬请期待. 1 ...
- 网络协议之bt---bt协议详解 DHT篇(下)
-------------------------author:pkf -------------------------------qq:1327706646 ------------------- ...
- 入木三分学网络第一篇--VRRP协议详解第一篇(转)
因为keepalived使用了VRRP协议,所有有必要熟悉一下. 虚拟路由冗余协议(Virtual Router Redundancy Protocol,简称VRRP)是解决局域网中配置静态网关时,静 ...
- http协议详解-经典篇
本文转载至 http://www.cnblogs.com/flychen/archive/2012/11/28/2792206.html ————————————————————————————— ...
- MySql-Binlog协议详解
Reference: https://blog.csdn.net/hj7jay/article/details/56665057?utm_source=blogxgwz7 MySql-Binlog协议 ...
- HTTP协议详解(一直在用可是这篇太好了转一下)
引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...
- TCP协议详解(理论篇)
TCP协议详解(理论篇) 2012-08-20 0个评论 作者:陈立龙 收藏 我要投稿 TCP协议详解(理论篇) 1. 与UDP不同的是,TCP提供了一种面向连接 ...
随机推荐
- OBIEE 11g 启动与停止包含服务器重启
ORACLE_BIEE_HOME为biee安装路径 注意:默认建立的是"instance1"但是如果你安装过多次可能实例名是不一样(例如: instance2以此类推).因此,请找 ...
- [转]Linux下权限掩码umask
本文转自:http://www.cnblogs.com/123-/p/4188942.html ---------------------------------------------------- ...
- Tomcat如何添加管理员
为Tomcat添加管理员,然后用管理员登录后就可以看到所有加载的工程包,以及运行的平台,还可以对项目进行管理,比如删和添加. 一.工具:apache-tomcat-7.0.39 二.添加步骤 1. 首 ...
- 2015年p2p网络借贷平台的发展现状
2015年春暖花开,莺飞草长,股市大涨大跌起起落落,P2P网络借贷收到越来越多的人关注,P2P网络借贷平台是p2p借贷与网络借贷相结合的金 融服务网站,这么多P2P网络借贷平台排我们应该如何选择呢?小 ...
- linux 下安装nodejs,CentOS 6.5 系统
本文采用nodejs 通过源码编译安装方式 编译需要gcc-c++编译器和openssl-devel库的支持,如果没有需要先安装. 在centos下可以先执行:yum install gcc-c++ ...
- (五) openwrt打包过程
标签(空格分隔): Makefile 本周是成胖子每周一博第六周,更好地阅读体验,请点击这里 前言 前面我们已经讲了openwrt编译的大部分过程,包括大致的编译步骤,ipk的编译等.今天是我这个系列 ...
- python类方法和静态方法
C++的静态方法是用static关键字,python j是没用static的. python中实现静态方法和类方法都是依赖于python的修饰器来实现的. class MyClass: def me ...
- [麦先生]Laravel SQL语句记录方式
打印sql语句,直接在你执行SQL语句后输出 方法一: $queries = DB::getQueryLog(); $a = end($queries); $tmp = str_replace('?' ...
- JavaWeb学习----JSTL标签库
一.JSTL简介: JSTL全名为JavaServer Pages Standard Tag Library,中文名称为JSP标准标签函数库,目前最新的版本为1.2.JSTL是由JCP(Java Co ...
- 城堡 (spfa+cheng)
[问题描述] 给定一张?个点?条边的无向连通图,每条边有边权.我们需要从?条边中选出? − 1条, 构成一棵树. 记原图中从 1 号点到每个节点的最短路径长度为? ? ,树中从 1 号点到每个节点的最 ...