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篇(上)的更多相关文章

  1. bt协议详解 DHT篇(下)

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

  2. bt协议详解 基础篇(上)

    bt协议详解 基础篇(上) 最近开发了一个免费教程的网站,产生了仔细了解bt协议的想法,所以写了这一篇文章,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术,敬请期待. 1 ...

  3. bt协议详解 基础篇(下)

    bt协议详解 基础篇(下) 最近开发了一个免费教程的网站,产生了仔细了解bt协议的想法,所以写了这一篇文章,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术,敬请期待. 1 ...

  4. 网络协议之bt---bt协议详解 DHT篇(下)

    -------------------------author:pkf -------------------------------qq:1327706646 ------------------- ...

  5. 入木三分学网络第一篇--VRRP协议详解第一篇(转)

    因为keepalived使用了VRRP协议,所有有必要熟悉一下. 虚拟路由冗余协议(Virtual Router Redundancy Protocol,简称VRRP)是解决局域网中配置静态网关时,静 ...

  6. http协议详解-经典篇

    本文转载至 http://www.cnblogs.com/flychen/archive/2012/11/28/2792206.html   ————————————————————————————— ...

  7. MySql-Binlog协议详解

    Reference: https://blog.csdn.net/hj7jay/article/details/56665057?utm_source=blogxgwz7 MySql-Binlog协议 ...

  8. HTTP协议详解(一直在用可是这篇太好了转一下)

    引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...

  9. TCP协议详解(理论篇)

    TCP协议详解(理论篇) 2012-08-20      0个评论       作者:陈立龙 收藏    我要投稿 TCP协议详解(理论篇)   1.    与UDP不同的是,TCP提供了一种面向连接 ...

随机推荐

  1. OBIEE 11g 启动与停止包含服务器重启

    ORACLE_BIEE_HOME为biee安装路径 注意:默认建立的是"instance1"但是如果你安装过多次可能实例名是不一样(例如: instance2以此类推).因此,请找 ...

  2. [转]Linux下权限掩码umask

    本文转自:http://www.cnblogs.com/123-/p/4188942.html ---------------------------------------------------- ...

  3. Tomcat如何添加管理员

    为Tomcat添加管理员,然后用管理员登录后就可以看到所有加载的工程包,以及运行的平台,还可以对项目进行管理,比如删和添加. 一.工具:apache-tomcat-7.0.39 二.添加步骤 1. 首 ...

  4. 2015年p2p网络借贷平台的发展现状

    2015年春暖花开,莺飞草长,股市大涨大跌起起落落,P2P网络借贷收到越来越多的人关注,P2P网络借贷平台是p2p借贷与网络借贷相结合的金 融服务网站,这么多P2P网络借贷平台排我们应该如何选择呢?小 ...

  5. linux 下安装nodejs,CentOS 6.5 系统

    本文采用nodejs 通过源码编译安装方式 编译需要gcc-c++编译器和openssl-devel库的支持,如果没有需要先安装. 在centos下可以先执行:yum install gcc-c++ ...

  6. (五) openwrt打包过程

    标签(空格分隔): Makefile 本周是成胖子每周一博第六周,更好地阅读体验,请点击这里 前言 前面我们已经讲了openwrt编译的大部分过程,包括大致的编译步骤,ipk的编译等.今天是我这个系列 ...

  7. python类方法和静态方法

    C++的静态方法是用static关键字,python j是没用static的. python中实现静态方法和类方法都是依赖于python的修饰器来实现的. class MyClass: def  me ...

  8. [麦先生]Laravel SQL语句记录方式

    打印sql语句,直接在你执行SQL语句后输出 方法一: $queries = DB::getQueryLog(); $a = end($queries); $tmp = str_replace('?' ...

  9. JavaWeb学习----JSTL标签库

    一.JSTL简介: JSTL全名为JavaServer Pages Standard Tag Library,中文名称为JSP标准标签函数库,目前最新的版本为1.2.JSTL是由JCP(Java Co ...

  10. 城堡 (spfa+cheng)

    [问题描述] 给定一张?个点?条边的无向连通图,每条边有边权.我们需要从?条边中选出? − 1条, 构成一棵树. 记原图中从 1 号点到每个节点的最短路径长度为? ? ,树中从 1 号点到每个节点的最 ...