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. JavaScript Patterns 3.8 Error Objects

    The error objects created by constructors(Error(),  SyntaxError(), TypeError(), and others) have the ...

  2. Less里css表达式的写法

    项目中用的grunt-contrib-less, 写了以下less代码 .mapfix{ position: fixed; top:10px; width: 430px; z-index: 100; ...

  3. [转]Android输出Log到文件

    前言:开发中遇到mx4这款机型Eclipse联调不上,logcat看不了,需要输出生成文件查看调试信息.网上搜了下,功能很完善了.startService和过滤输出信息需要自己添加设置,另外注意添加权 ...

  4. Ubuntu 安装libusb

    执行以下指令 sudo apt-get install libusb-dev sudo apt-get install libusb-1.0-0-dev

  5. 2014 Super Training #8 G Grouping --Tarjan求强连通分量

    原题:ZOJ 3795 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3795 题目大意:给定一个有向图,要求把点分为k个集 ...

  6. Unity原厂讲师大解密

    Asset Bundle工作流程及人物换装实例- 刘刚 Unity内部的资源有两种 Resources:有10年历史,尽量用资产包 Asset Bundle:昵称AB,现今Unity处理资源的中心 A ...

  7. 用SqlParameter 给SQL传递参数

    1.数据访问层 using的用法: 01.可以using System;导命名控空间 02.using 的语法结构 using(变量类型  变量名 =new 变量类型()) { } 案例: 03.us ...

  8. iOS app上传错误集锦(转载)

    1.工程里增加了版本自动更新. 2.未增加判断网络状态的类Reachability. 3.问题:error itms -90049 This bundel is invalid. The bundle ...

  9. mysqli常用错误处理函数

    mysqli扩展库包含三个类库,分别是mysqli连接库,mysqli_result处理结果集库和预处理库: 当使用select语句返回的结果集就是mysqli_result类库的对象,所以就可以用这 ...

  10. Python-操作Memcache、Redis、RabbitMQ、

    Memcache 简述: Memcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的.需要 ...