DHT网络

@(基础技术)

现在有一种方法,可以通过磁力链接,例如magnet:?xt=urn:btih:0482e0811014fd4cb5d207d08a7be616a4672daa,就可以获取BT文件。
这个是通过DHT网络来实现的。
DHT网络是一个去中心化的,分布式信息存储系统。
存储的信息就是bt文件。

一、节点

每一台电脑,就是一个节点。它既是客户端,也是服务端。
每个节点都有一个节点ID,IP地址和端口号(节点进程的端口)。
节点ID由160位的二进制字符串组成,也就是长度为32的16进制字符串,跟我们常用的md5一样。
通过异或算法,可以计算两个节点ID的距离。例如01和00的异或结果是01,也就是距离是1。

二、路由表

每个节点都会保存一个路由表,保存其他节点的信息,节点信息包括:节点ID,节点的IP地址和端口号。
路由表中,会有多个bucket,例如bucket-1,bucket-2等等。
bucket-i保存的是与自身节点ID距离为[2^i-1,2^i)的节点信息
每个nodeid可以理解为深度是160的二叉树,二bucket-i就是自身的叶子的第i个父节点的兄弟节点的所有叶子节点(不太严谨)
如下图:
Alt text

所以i最大值是160。

而为什么要这么存了?
这样存是为了可以快速找到目标节点N2。
例如自身的节点ID是N1,需要寻找N2的IP和端口号。

  • 计算N1和N2的距离D
  • 从bucket-D,找一个节点N3,如果N3=N2,就找到了,否则就向N3发送寻找节点N2的请求
  • N3接收到请求后,计算N2和N3的距离D1,从N3的路由表里面的bucket-D1,找到一个节点N4,返回N4的信息给N1
  • N1收到返回后,如果N4=N2,就找到了,否则继续向N4发送寻找节点N2的请求。一直递归。

因为N2和N3会处于同一个bucket,所以他们的距离D1不会超过D/2,所以每一次循环,获得的节点NN与N2的距离都会比之前的请求缩小1倍。所以时间复杂度是logN。跟二分查找是一样的。

三、信息发布

当发布者,需要发布信息(例如一个bt文件)到DHT网络。

  • 发布者会计算信息的md5,M1
  • 通过发布者的路由表,查询与M1的距离小于等于K的多个节点
  • 向这些节点发送保存信息(Store)的请求,就会把信息存储在这些节点上

k一般要大于1。不然只会把信息存储在一个节点上,万一节点下线,或者退出网络,就会导致信息不能被找到。

四、数据包

节点与节点之间,通过UDP协议,传输数据包来通讯。
DHT网络的数据包都是json格式。
必须字段:

  • t:消息的id。因为是UDP传输,所以要带上消息ID,不要就不知道每个包对应是哪个包的回复。
  • y:数据包的类型,取值可以是:
    • q,请求包
    • r,回复包
    • e,错误包,其实也是回复的一种

      1. 请求和回复包

      请求包必须字段
  • q,请求的类型,
    • ping 嗅探Node是否可用
    • find_node。寻找Node的请求
    • get_peers。寻找有资源的Node
    • announce_peer ,请求下载资源
  • a,请求的参数,类型是json里面的字典

回复包必须字段:
*r 回复的内容,字典

1.1ping

请求包
a包含字段

  • id,请求者的nodeid

包例子

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

回复包
r包含字段

  • id 回复者的nodeid

包例子

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

1.2find_node

请求包
a包含字段

  • id,请求者的nodeid
  • target,需要寻找的Node的nodeid

包例子:

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

回复包
r包含字段

  • id 回复者的nodeid
  • nodes 在回复者的路由表中,与请求的target 的nodeid最接近的几个节点的信息,包含节点的ip,端口,nodeid。

包例子

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

1.3 get_peers

请求包
a包含字段

  • id,请求者的nodeid
  • info_hash 寻找的资源的hash
  • token 密钥

包例子

{"t":"aa", "y":"q","q":"get_peers", "a":{"id":"abcdefghij0123456789","info_hash":"mnopqrstuvwxyz123456"}}

回复包
如果回复者的路由表中,有存有info_hash资源的节点信息,就返回value,否则返回node,node的值和find_node一样
r包含字段

  • id 回复者的nodeid
  • value,拥有info_hash的节点信息
  • nodes 和find_node的nodes一样

包例子

{"t":"aa", "y":"r", "r":{"id":"abcdefghij0123456789", "token":"aoeusnth","values": ["axje.u", "idhtnm"]}}

1.4 announce_peer

请求包
a包含字段

  • id,请求者的nodeid
  • info_hash 寻找的资源的hash
  • token 密钥
  • port,下载资源的端口

包例子

{"t":"aa", "y":"q","q":"announce_peer", "a":{"id":"abcdefghij0123456789","info_hash":"mnopqrstuvwxyz123456", "port":6881, "token": "aoeusnth"}}

回复包
r包含字段

  • id 回复者的nodeid

包例子

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

2. 错误包

  • e 列表类型,第一个元素时错误id,第二个是错误的说明

    {"t":"aa", "y":"e", "e":[201,"A Generic Error Ocurred"]}

错误类型有:

  • 201 一般错误
  • 202 服务错误
  • 203 协议错误,比如不规范的包,无效的参数,或者错误的token
  • 204 未知方法

五、工作流程

1.初始化

  • 向一个固定的服务器,获取节点ID,完成冷启动
  • 不断向已知的节点发送find_node请求,让自己的路由表里面的节点更多

2. 根据磁力链接,获取信息(bt文件)

  • 获取磁力链接里面的md5,转换为二进制M1。
  • 通过路由表,获取与M1距离最近的节点,然后向它们发送announce_peer 请求。如果节点有我们想要的信息,就会把信息发过来,这样我们就获取到了bt文件了。

六、DHT网络中收集bt文件的原理

向三个固定服务器发送find_node的请求,target是随机的nodeid或者是自己的nodeid,N1
服务器返回最接近N1的的3个nodeid的信息,这些信息是一个加密了的,固定协议的字符串,里面有node的ip,port和nodeid。自身节点把所有的node存储到路由表
新开一个线程,对node,再发送find_node请求,这时自己的nodeid是随机的
这样,就会导致在很多个DHTNode中,都有我们ip和端口的信息,而且映射到很多不同的nodeid
这样别人去这些DHTNode中寻找bt资源的时候,这些Node就很可能会返回我们的IP,PORT给别人,那么别人就会向我们发送announce_peer的请求,这样我们就能拿到bt文件了

  1. 初始化,目的是让自己的nodeid加入到DHT网络中,并认识尽量多的其他node,放到我们的路由表。
    1. 生成自己的nodeid。
    2. 向固定的服务器(例如:),发送find_node请求,target是自己的nodeid,这样,自己的nodeid就会进入到固定服务器的路由表,这样其他node想固定服务器发送find_node请求的话,固定服务器就会返回我们的nodeid给他们,这样我们的nodeid就会进入很多其他Node的路由表了。
    3. 发送给固定服务器的find_node请求中,会返回我们附近的node的信息,保存到我们自己的路由表
  2. 接收其他节点的请求。当我们加入到DHT网络中,就会有其他节点发送请求给我们。下面的请求处理完后,我们都把请求者加入到我们的路由表中。
    1. 当我们收到ping请求,就返回自己的id给它,表示自己在正常运行。
    2. 当我们收到find_node请求, 就从我们的路由表查找离target最近的N个node的信息,返回给它。
    3. 当我们收到get_peers请求,就从我们的路由表中查找拥有该资源的peers信息,返回给它。
    4. 当我们收到announce_peer 请求,就从发送info_hash的资源到对应的端口

七、Bt文件下载原理

当得到BT文件后,就可以用bt文件下载器进行文件的下载
BT文件里面包含

  • tracket地址
  • 目标文件列表,和分块信息。每一块是2k的倍数。分块信息包含每一个分块的索引和MD5
  • BT文件的基本信息,如标题,每个文件的大小和文件名等

下载流程

  • 下载器请求tracket地址,获取其他也在下载该bt文件的节点信息
  • 下载器连接其他节点,告诉自身缺少的分块的索引和获取到对方缺少的分块索引
  • 如果自身有分块1,而对方没有,就向对方发送分块1
  • 如果对方有分块2,而自身没有,就接收分块2
  • 接收完一个分块后,计算md5,然后和bt文件里面的md5对比,如果正确,就下载完成,否则要重新下载。

所以bt文件的下载过程,并不是去中心化的,tracket服务器就是一个中心化的服务器。
tracket服务器只管理下载节点的信息,并不会存储文件的具体分块。所以压力也比较小。
节点越多,下载的速度越快。

参考

未经允许,请不要转载

转载于:https://www.cnblogs.com/Xjng/p/10616158.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/278081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node文件模块

在上一篇文章中有提到,Node模块分为核心模块和文件模块,接下来就简单总结一下文件模块。 文件模块则是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、速度相比核心模块稍微慢一些,但是用的非常多。这些模块需要我…

PHP GD库解析一张简单图片并输出

这里只演示一下2种颜色值的图片&#xff0c;简单描述下概念。 首先要安装下GD库。否则下面的代码运行不了。 $size getimagesize(2.png); // 获取图片大小 $res imagecreatefrompng(2.png); // 获取指定图片的资源对象for ($i 0; $i < $size[1]; $i) {for ($j 0; $j &…

开发Teams的messaging extension

什么是Messaging Extension Messaging Extension是微软Teams的一种十分有用的扩展方式。可以让用户发送adaptive cards。具体的说明不在这里展开了。可以阅读微软官方的详细说明&#xff1a; https://docs.microsoft.com/en-gb/microsoftteams/platform/concepts/messaging-e…

归并排序(转)

转载自&#xff1a;https://www.cnblogs.com/chengxiao/p/6194356.html 归并排序&#xff08;MERGE-SORT&#xff09;是利用归并的思想实现的排序方法&#xff0c;该算法采用经典的分治&#xff08;divide-and-conquer&#xff09;策略&#xff08;分治法将问题分(divide)成一些…

Site24x7 为Teams提供可智能 DevOps

我们生活在一个云的时代, SaaS 应用程序每天都在推动我们的生产力。作为一个消费者, 很难想象如果你最喜欢的应用无法访问&#xff0c;即使只是一秒钟无法访问。作为 SaaS业务, 更难以想象您的服务面临停机, 每一分钟停止服务都会花费大量的资金, 当然还损失客户的信任。Site24…

XUbuntu22.04之跨平台容器格式工具:MKVToolNix(二百零三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

redis集群搭建踩坑笔记

推荐参考教程&#xff1a;https://blog.csdn.net/pucao_cug/article/details/69250101 错误&#xff1a; from /usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in require from /usr/local/redis-3.0.6/src/redis-trib.rb:25:in <main> 解决&#xff1a; g…

Docker 创建镜像

文章首发自个人网站&#xff1a;https://www.exception.site/docker/docker-create-image 本文中&#xff0c;您将学习 Docker 如何创建镜像&#xff1f;Docker 创建镜像主要有三种&#xff1a; 基于已有的镜像创建&#xff1b;基于 Dockerfile 来创建&#xff1b;基于本地模板…

使用Azure Pipelines来实现Teams App的CI

我在之前的文章里介绍了如何一步步配置CI/CD来部署Teams App( 之前的文章 )&#xff0c;随着Azure DevOps的发展&#xff0c;微软推出了Azure Pipelines。在这篇文章中&#xff0c;主要介绍什么是Azure Pipelines&#xff0c;以及如何使用Azure Pipelines来进行Teams App的构建…

004-React入门概述

一、概述 参考地址&#xff1a;https://reactjs.org/docs/try-react.html 1.1、本地快速体验 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>Hello World</title><script src"https://unpkg.com/react16/…

开发Teams Tabs应用程序

什么是Teams Tabs Tabs是微软Teams的一种十分有用的扩展方式。可以非常方便的和现有的网站或者网页应用进行整合。具体的说明不在这里展开了。可以阅读微软官方的详细说明&#xff1a; https://docs.microsoft.com/en-gb/microsoftteams/platform/concepts/tabs/tabs-overvie…

(转)关于SimpleDateFormat安全的时间格式化线程安全问题

想必大家对SimpleDateFormat并不陌生。SimpleDateFormat 是 Java 中一个非常常用的类&#xff0c;该类用来对日期字符串进行解析和格式化输出&#xff0c;但如果使用不小心会导致非常微妙和难以调试的问题&#xff0c;因为 DateFormat 和 SimpleDateFormat 类不都是线程安全的&…

IDEA开发工具的学习

1.设置jdk的版本 &#xff0c;快捷键&#xff1a;ctrl shirt alt s 打开项目的设置&#xff0c;选择Project 进行 jdk版本的设置。 2.鼠标移到项目上&#xff0c;右键&#xff0c;Show in Explorer 定位到当前项目对应的文件夹中 3.每次关闭项目时&#xff0c;需要手动选择Fi…

顺利达成微软HacktoberFest 2018

昨天收到邮件&#xff0c;我的HacktoberFest 2018奖品终于从美国寄出来了&#xff0c;不知道飘洋过海多久可以寄到。 今年的HacktoberFest 2018除了微软官方博客的宣传&#xff0c;连Channel 9的美女主播也在TWC上大肆宣传。 活动内容是在整个10月份需要给微软的开源代码贡献5…

更新!在线状态和用户的共存模式保持一致

根据用户反馈&#xff0c;我们正在改进&#xff1a;当组织同时使用Microsoft Teams和Skype for Business时的用户在线状态。通过此更新&#xff0c;路由和在线状态将完全保持一致。为确保路由能跟随用户的在线状态&#xff0c;所以在线状态的更新现在会基于用户的共存模式。 如…

centos上安装supervisor来管理dotnetcore等应用程序

supervisor 介绍&#xff1a;这是一款用python编写的进程管理工具&#xff0c;可以守护他管理的所有进程&#xff0c;防止异常退出&#xff0c;以及提供一个可视化的web界面来手动管理&#xff0c;打开关闭重启各种应用&#xff0c;界面如下&#xff1a;关于在centos上安装supe…

新增功能!Trello个人应用程序登陆 Microsoft Teams

从初创企业到《财富》500强公司, Trello是团队在任何项目上进行合作的视觉方式。在Microsoft Teams中, 我们发现围绕项目进行大量对话和协作的方式。因此, 一个首屈一指的项目管理工具应该与团队协作的终极枢纽进行合作, 以便让员工更好地一起工作。 如你所知, 我们已经为Micr…

Linux bc 命令简单学习

1. bash里面能够实现比较简单的四则运算 echo $((10*20)) 注意是 双括号 $ 地址符号. 2. 但是比较复杂的 可能就难以为继了 比如不支持精度 3. 所以这里面需要使用 bc 命令来执行相关的操作. man 内容: usage: bc [options] [file ...] -h --help print this usage and exit…

终于收到HacktoberFest的奖品啦

去年10月份给微软repo提交了5个PR&#xff0c;达成了HacktoberFest 2018&#xff0c;今天终于收到了从美国到澳洲&#xff0c;飘洋过海&#xff0c;姗姗来迟的T-shirt&#xff0c;不过大小正好。算是新年礼物了&#xff0c;哈哈

三、SpringBoot-application.properties配置文件和application.yml配置文件

其实SpringBoot的配置文件有.properties和.yml两种形式&#xff0c;两种配置文件的效果类似&#xff0c;只不过是格式不同而已&#xff0c;孩儿们可以根据下面这几种张截图&#xff0c;通过对比端口号的配置&#xff0c;以及连接SQLServer数据库的配置的书写格式来自己体会两者…