日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

不是吧!你还不懂DHT协议?

發(fā)布時(shí)間:2024/8/1 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 不是吧!你还不懂DHT协议? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 前文回顧
  • 前提說明
  • 概述
    • 尋找節(jié)點(diǎn)的過程
    • Token令牌
  • 路由表
  • KRPC協(xié)議
    • 請(qǐng)求
    • 回復(fù)
    • 錯(cuò)誤
  • DHT中的4種請(qǐng)求
    • ping
    • find_node
    • get_peers
      • 補(bǔ)充知識(shí)
    • announce_peer
  • DHT網(wǎng)絡(luò)爬蟲和Python爬蟲的區(qū)別

前文回顧

如果還不懂DHT網(wǎng)絡(luò),可以先看這篇文章。理解了DHT網(wǎng)絡(luò),后面的內(nèi)容才看得明白。
別再裝純說不懂BT種子了

前提說明

BitTorrent使用了“分布式哈希表”(DHT)為沒有Tracker的種子(torrent)存儲(chǔ)了peer之間的聯(lián)系信息。這樣每個(gè)peer都成了Tracker。

DHT是基于kademlim網(wǎng)絡(luò),并且在UDP上實(shí)現(xiàn)的。

DHT 由節(jié)點(diǎn)組成,它存儲(chǔ)了 peer 的位置。BitTorrent 客戶端包含一個(gè) DHT 節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)用來聯(lián)系 DHT 中其他節(jié)點(diǎn),從而得到 peer 的位置,進(jìn)而通過 BitTorrent 協(xié)議下載。

解釋說明
“peer”: 在一個(gè) TCP 端口上監(jiān)聽的客戶端/服務(wù)器,它實(shí)現(xiàn)了 BitTorrent 協(xié)議。簡單理解就是一臺(tái)電腦,但是端口號(hào)是基于TCP連接的

“節(jié)點(diǎn)”: 在一個(gè) UDP 端口上監(jiān)聽的客戶端/服務(wù)器,它實(shí)現(xiàn)了 DHT(分布式哈希表) 協(xié)議。簡單理解也是一臺(tái)電腦,但是端口號(hào)是基于UDP連接的

“BitTorrent客戶端”:指的是迅雷這些BT軟件等

概述

每個(gè)節(jié)點(diǎn)有一個(gè)全局唯一的標(biāo)識(shí)符,作為 “node ID”。

每個(gè)節(jié)點(diǎn)都維護(hù)一個(gè)路由表,路由表中包含一部分節(jié)點(diǎn)的信息。每個(gè)節(jié)點(diǎn)都知道在DHT網(wǎng)絡(luò)中離自己很近的節(jié)點(diǎn),離自己很遠(yuǎn)的節(jié)點(diǎn)知道的很少。

尋找節(jié)點(diǎn)的過程

1、 當(dāng)節(jié)點(diǎn)要為種子尋找peer時(shí),它將自己的節(jié)點(diǎn)的哈希值(40位16進(jìn)制字符)和種子的哈希值進(jìn)行距離計(jì)算(異或算法)

2、 向路由表中離種子最近的節(jié)點(diǎn)發(fā)送請(qǐng)求,問他們正在下載種子的peer的信息

3、 被聯(lián)系的節(jié)點(diǎn)如果知道下載種子的peer信息,那它將peer的信息回復(fù)給當(dāng)前的節(jié)點(diǎn)。如果不知道,將回復(fù)離種子最近的peer的節(jié)點(diǎn)信息,讓當(dāng)前節(jié)點(diǎn)去請(qǐng)求離種子最近的peer。

4、 重復(fù)3步驟,直到不能找到離種子更近的節(jié)點(diǎn)信息。

5、 在查詢完之后,客戶端把自己作為peer信息,插入到所有回復(fù)節(jié)點(diǎn)中離種子最近的那個(gè)節(jié)點(diǎn)中。

Token令牌

如果一個(gè)節(jié)點(diǎn)宣布它所控制的 peer 正在下載一個(gè)種子,它必須在回復(fù)節(jié)點(diǎn)的同時(shí),附加上對(duì)方向我們發(fā)送的最近的”令牌(token)”。Token令牌是用來核對(duì)信息的。主要體現(xiàn)在get_peer和announce_peer中,后面還會(huì)介紹。

路由表

每個(gè)節(jié)點(diǎn)都維護(hù)一個(gè)路由表,這個(gè)路由表保存著已知的好節(jié)點(diǎn)。路由表中的節(jié)點(diǎn)作為DHT請(qǐng)求的起始點(diǎn)。

這里的好節(jié)點(diǎn)是指在過去的 15 分鐘以內(nèi),曾經(jīng)對(duì)我們的某一個(gè)請(qǐng)求給出過回復(fù)的節(jié)點(diǎn),或者曾經(jīng)對(duì)我們的請(qǐng)求給出過一個(gè)回復(fù)(不用在15分鐘以內(nèi)),并且在過去的 15 分鐘給我們發(fā)送過請(qǐng)求。

還記得桶的概念嗎?桶里裝的都是好節(jié)點(diǎn),一旦某個(gè)節(jié)點(diǎn)變壞了,我們就會(huì)用好的節(jié)點(diǎn)替代它。怎么確定是壞的節(jié)點(diǎn)呢?我們會(huì)向它發(fā)送ping請(qǐng)求,給出回復(fù)的是好的節(jié)點(diǎn)。

KRPC協(xié)議

KRPC協(xié)議是由bencode編碼組成RPC結(jié)構(gòu),使用UDP報(bào)文發(fā)送。

包含3種消息:請(qǐng)求、回復(fù)、錯(cuò)誤

在DHT協(xié)議中,請(qǐng)求又分為四種:ping、find_node、get_peers、announce_peer

一條KRPC 消息由一個(gè)獨(dú)立的字典組成,其中有 2 個(gè)關(guān)鍵字是所有的消息都包含的,其余的附加關(guān)鍵字取決于消息類型。

每條消息都包含 t 關(guān)鍵字,它是一個(gè)代表了 transaction ID 的字符串類型。transaction ID 由請(qǐng)求節(jié)點(diǎn)產(chǎn)生,并且回復(fù)中要包含回顯該字段,所以回復(fù)可能對(duì)應(yīng)一個(gè)節(jié)點(diǎn)的多個(gè)請(qǐng)求。簡單理解transaction ID就是一個(gè)請(qǐng)求的唯一標(biāo)識(shí)

另外每個(gè) KRPC 消息還應(yīng)該包含的關(guān)鍵字是 y,它由一個(gè)字節(jié)組成,表明這個(gè)消息的類型。y 對(duì)應(yīng)的值有三種情況:q 表示請(qǐng)求,r 表示回復(fù),e 表示錯(cuò)誤。

請(qǐng)求

請(qǐng)求,對(duì)應(yīng)于 KPRC 消息字典中的 y 關(guān)鍵字的值是 q,它包含 2 個(gè)附加的關(guān)鍵字 q 和 a。關(guān)鍵字 q 是字符串類型,包含了請(qǐng)求的方法名字。(請(qǐng)求方法的名字就是ping、find_node、get_peers、announce_peer)關(guān)鍵字 a 一個(gè)字典類型包含了請(qǐng)求所附加的參數(shù)。

回復(fù)

回復(fù),對(duì)應(yīng)于 KPRC 消息字典中的 y 關(guān)鍵字的值是 r,包含了一個(gè)附加的關(guān)鍵字 r。關(guān)鍵字 r 是字典類型,包含了返回的值。發(fā)送回復(fù)消息是在正確解析了請(qǐng)求消息的基礎(chǔ)上完成的。

錯(cuò)誤

錯(cuò)誤,對(duì)應(yīng)于 KPRC 消息字典中的 y 關(guān)鍵字的值是 e,包含一個(gè)附加的關(guān)鍵字 e。關(guān)鍵字 e 是列表類型。第一個(gè)元素是數(shù)字類型,表明了錯(cuò)誤碼。第二個(gè)元素是字符串類型,表明了錯(cuò)誤信息。當(dāng)一個(gè)請(qǐng)求不能解析或出錯(cuò)時(shí),錯(cuò)誤包將被發(fā)送。

DHT中的4種請(qǐng)求

所有的請(qǐng)求都包含一個(gè)關(guān)鍵字 id,它包含了請(qǐng)求節(jié)點(diǎn)的節(jié)點(diǎn) ID。所有的回復(fù)也包含關(guān)鍵字 id,它包含了回復(fù)節(jié)點(diǎn)的節(jié)點(diǎn) ID。

說明
節(jié)點(diǎn)ID(20位字節(jié)的字符串)和節(jié)點(diǎn)的哈希值即node節(jié)點(diǎn)ID(40位16進(jìn)制的字符串)是不同的,不要搞混了。

ping

最基礎(chǔ)的請(qǐng)求就是 ping。這時(shí) KPRC 協(xié)議中的 “q” = “ping”。

Ping 請(qǐng)求包含一個(gè)參數(shù) id,它是一個(gè) 20 字節(jié)的字符串包含了發(fā)送者網(wǎng)絡(luò)字節(jié)序的節(jié)點(diǎn) ID。

對(duì)應(yīng)的 ping 回復(fù)也包含一個(gè)參數(shù) id,包含了回復(fù)者的節(jié)點(diǎn) ID。

報(bào)文示例

ping Query = {"t":"aa", "y":"q","q":"ping", "a":{"id":"abcdefghij0123456789"}} Response = {"t":"aa", "y":"r", "r": {"id":"mnopqrstuvwxyz123456"} }

find_node

find_node 被用來查找給定 ID 的節(jié)點(diǎn)的聯(lián)系信息。這時(shí) KPRC 協(xié)議中的 “q” == “find_node”。

find_node 請(qǐng)求包含 2 個(gè)參數(shù),第一個(gè)參數(shù)是 id,包含了請(qǐng)求節(jié)點(diǎn)的ID。第二個(gè)參數(shù)是 target,包含了請(qǐng)求者正在查找的節(jié)點(diǎn)的 ID。

當(dāng)一個(gè)節(jié)點(diǎn)接收到了 find_node 的請(qǐng)求,他應(yīng)該給出對(duì)應(yīng)的回復(fù),回復(fù)中包含 2 個(gè)關(guān)鍵字 id 和 nodes,nodes 是字符串類型,包含了被請(qǐng)求節(jié)點(diǎn)的路由表中最接近目標(biāo)節(jié)點(diǎn)的 K(8) 個(gè)最接近的節(jié)點(diǎn)的聯(lián)系信息。

報(bào)文示例

find_node Query = {"t":"aa", "y":"q","q":"find_node", "a": {"id":"abcdefghij0123456789","target":"mnopqrstuvwxyz123456"}} Response = {"t":"aa","y":"r","r": {"id":"0123456789abcdefghij","nodes": "def456..."}}

get_peers

get_peers 與 torrent 文件的 infohash 有關(guān)。

這時(shí) KPRC 協(xié)議中的 “q” = “get_peers”。get_peers 請(qǐng)求包含 2 個(gè)參數(shù)。第一個(gè)參數(shù)是 id,包含了請(qǐng)求節(jié)點(diǎn)的 ID。第二個(gè)參數(shù)是 info_hash,它代表 torrent 文件的 infohash。

如果被請(qǐng)求的節(jié)點(diǎn)有對(duì)應(yīng) info_hash 的 peers,他將返回一個(gè)關(guān)鍵字 values,這是一個(gè)列表類型的字符串。每一個(gè)字符串包含了 “CompactIP-address/portinfo” 格式的 peers 信息。如果被請(qǐng)求的節(jié)點(diǎn)沒有這個(gè) infohash 的 peers,那么他將返回關(guān)鍵字 nodes,這個(gè)關(guān)鍵字包含了被請(qǐng)求節(jié)點(diǎn)的路由表中離 info_hash 最近的 K 個(gè)節(jié)點(diǎn),使用 “Compactnodeinfo” 格式回復(fù)。

在這兩種情況下,關(guān)鍵字 token 都將被返回。token 關(guān)鍵字在今后的 annouce_peer 請(qǐng)求中必須要攜帶。token 是一個(gè)短的二進(jìn)制字符串。

報(bào)文格式

get_peers Query = {"t":"aa", "y":"q", "q":"get_peers", "a": {"id":"abcdefghij0123456789", "info_hash":"mnopqrstuvwxyz123456"}} Response with peers = {"t":"aa","y":"r", "r": {"id":"abcdefghij0123456789","token":"aoeusnth","values": ["axje.u", "idhtnm"]}} Response with closest nodes = {"t":"aa","y":"r","r": {"id":"abcdefghij0123456789", "token":"aoeusnth","nodes": "def456..."}}

補(bǔ)充知識(shí)

聯(lián)系信息編碼 Contact Encoding

Peers 的聯(lián)系信息被編碼為 6 字節(jié)的字符串。又被稱為 “CompactIP-address/port info”,其中前 4 個(gè)字節(jié)是網(wǎng)絡(luò)字節(jié)序的 IP 地址,后 2 個(gè)字節(jié)是網(wǎng)絡(luò)字節(jié)序的端口。

節(jié)點(diǎn)的聯(lián)系信息被編碼為 26 字節(jié)的字符串。又被稱為 “Compactnode info”,其中前 20 字節(jié)是網(wǎng)絡(luò)字節(jié)序的節(jié)點(diǎn) ID,后面 6 個(gè)字節(jié)是 peers 的 “CompactIP-address/port info”

announce_peer

這個(gè)請(qǐng)求用來表明發(fā)出 announce_peer 請(qǐng)求的節(jié)點(diǎn),正在某個(gè)端口下載 torrent 文件。

announce_peer 包含 4 個(gè)參數(shù)。

第一個(gè)參數(shù)是 id,包含了請(qǐng)求節(jié)點(diǎn)的 ID;

第二個(gè)參數(shù)是 info_hash,包含了 torrent 文件的 infohash;

第三個(gè)參數(shù)是 port 包含了整型的端口號(hào),表明 peer 在哪個(gè)端口下載;

第四個(gè)參數(shù)數(shù)是 token,這是在之前的 get_peers 請(qǐng)求中收到的回復(fù)中包含的。

收到 announce_peer 請(qǐng)求的節(jié)點(diǎn)必須檢查這個(gè) token 與之前我們回復(fù)給這個(gè)節(jié)點(diǎn) get_peers 的 token 是否相同。如果相同,那么被請(qǐng)求的節(jié)點(diǎn)將記錄發(fā)送 announce_peer 節(jié)點(diǎn)的 IP 和請(qǐng)求中包含的 port 端口號(hào)在 peer 聯(lián)系信息中對(duì)應(yīng)的 infohash 下

報(bào)文示例

announce_peers Query = {"t":"aa","y":"q", "q":"announce_peer", "a": {"id":"abcdefghij0123456789", "implied_port": 1, "info_hash":"mnopqrstuvwxyz123456", "port": 6881, "token": "aoeusnth"}} Response = {"t":"aa","y":"r", "r": {"id":"mnopqrstuvwxyz123456"}}

DHT網(wǎng)絡(luò)爬蟲和Python爬蟲的區(qū)別

要想成功編寫出DHT網(wǎng)絡(luò)爬蟲,DHT網(wǎng)絡(luò)協(xié)議必須弄明白。

DHT爬蟲,就是把自己偽裝成DHT網(wǎng)絡(luò)中的一個(gè)節(jié)點(diǎn),當(dāng)某個(gè)客戶端想要下載某個(gè)torrent文件時(shí),就會(huì)在DHT網(wǎng)絡(luò)上發(fā)起廣播,當(dāng)它詢問我的節(jié)點(diǎn)時(shí),我就知道:哦,原來有人下載這個(gè)種子,那么在DHT網(wǎng)絡(luò)上肯定有這個(gè)種子。于是我把這個(gè)種子的信息保存到我的數(shù)據(jù)庫。

Python 爬蟲,是主動(dòng)出擊,盲目尋找。在互聯(lián)網(wǎng)的海量網(wǎng)頁中尋找種子和磁力鏈接。而 DHT 爬蟲則變成了被動(dòng)等待,當(dāng)別人來詢問時(shí),就把它的詢問結(jié)果記錄下來,如果一個(gè)種子被詢問了很多次,則說明這個(gè)種子是一個(gè)熱門種子,這是 Python 爬蟲無法做到的。

簡單總結(jié):python爬蟲是主動(dòng)出擊,而DHT爬蟲是被動(dòng)等待。

總結(jié)

以上是生活随笔為你收集整理的不是吧!你还不懂DHT协议?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。