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.pswp.cn/news/278081.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/278081.shtml
英文地址,請注明出處:http://en.pswp.cn/news/278081.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java基礎 Day04(個人復習整理)

分支結構 2、switch語句 因為if語句的級聯式最多只會處理三種情況,如果出現多情況 1>可以繼續使用if語句的級聯式,但是可能代碼的可讀性就會變差。  2>采用switch語句來解決。 switch語法格式: switch (存在多種情況的變量) {case 值…

java如何獲取一個double的小數位數

前言 看標題是不是覺得這是一個很簡單的問題,我一開始也是這么認為的,但是實際情況下,在各種情況下我們都進行了測試,發現很多實際情況是無法不盡如人意的。 方法分析 當前能想到的比較容易有下面幾種 1、直接使用double處理 2、將…

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 &…

Permutations CodeForces - 736D (矩陣逆)

對于刪除每個對(x,y), 可以發現他對答案的貢獻為代數余子式$A_{xy}$ 復習了一下線代后發現代數余子式可以通過伴隨矩陣求出, 即$A_{xy}A^*[y][x]$, 伴隨矩陣$A^*|A|A^{-1}$可以通過高斯消元$O(\frac{n^3}{\omega})$求出 #include <iostream> #include <algorithm> …

開發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;基于本地模板…

hdfoo站點開發筆記

為了安全,也要兼顧編輯器切換管理 開發時不必管目錄名稱的事, 只是在部署的時候,才修改應用目錄和tp目錄的名字就行了. 為了提高tp的加載效率, 始終給app和tp以絕對路徑.就是以 realpath來定位 realpath返回的就是 一個絕對路徑, 在lx中是以 斜杠 根樹開始的. 參數可以是文件名…

論文致謝

這篇致謝語&#xff0c;是我論文的最后一節&#xff0c;也是我放在最后的最后寫的內容。之所以拖到最后&#xff0c;是因為我不知道該用怎么的方式來結束我的論文。我想&#xff0c;要結束的不只是文章&#xff0c;還是研究生生涯&#xff0c;是我在廈門大學三年來的一切&#…

使用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/…

Python --- 卸載

python的卸載 1、? rpm -qa|grep python3.6|xargs rpm -ev --allmatches --nodeps ##強制刪除已安裝程序及其關聯 2、? whereis python3.6 |xargs rm -frv 允許你對輸出執行其他某些命令 3、? whereis python ##驗證刪除&#xff0c;返回無結果轉載于:https://www.…

開發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…