@(基礎技術)node
如今有一種方法,能夠經過磁力連接,例如magnet:?xt=urn:btih:0482e0811014fd4cb5d207d08a7be616a4672daa
,就能夠獲取BT文件。
這個是經過DHT網絡來實現的。
DHT網絡是一個去中心化的,分佈式信息存儲系統。
存儲的信息就是bt文件。算法
每一臺電腦,就是一個節點。它既是客戶端,也是服務端。
每一個節點都有一個節點ID,IP地址和端口號(節點進程的端口)。
節點ID由160位的二進制字符串組成,也就是長度爲32的16進制字符串,跟咱們經常使用的md5同樣。
經過異或算法,能夠計算兩個節點ID的距離。例如01和00的異或結果是01,也就是距離是1。json
每一個節點都會保存一個路由表,保存其餘節點的信息,節點信息包括:節點ID,節點的IP地址和端口號。
路由表中,會有多個bucket,例如bucket-1,bucket-2等等。
bucket-i保存的是與自身節點ID距離爲[2^i-1,2^i)的節點信息
每一個nodeid能夠理解爲深度是160的二叉樹,二bucket-i就是自身的葉子的第i個父節點的兄弟節點的全部葉子節點(不太嚴謹)
以下圖:
服務器
因此i最大值是160。網絡
而爲何要這麼存了?
這樣存是爲了能夠快速找到目標節點N2。
例如自身的節點ID是N1,須要尋找N2的IP和端口號。分佈式
由於N2和N3會處於同一個bucket,因此他們的距離D1不會超過D/2,因此每一次循環,得到的節點NN與N2的距離都會比以前的請求縮小1倍。因此時間複雜度是logN。跟二分查找是同樣的。加密
當發佈者,須要發佈信息(例如一個bt文件)到DHT網絡。.net
k通常要大於1。否則只會把信息存儲在一個節點上,萬一節點下線,或者退出網絡,就會致使信息不能被找到。線程
節點與節點之間,經過UDP協議,傳輸數據包來通信。
DHT網絡的數據包都是json格式。
必須字段:code
e,錯誤包,其實也是回覆的一種
回覆包必須字段:
*r 回覆的內容,字典
請求包
a包含字段
包例子
{"t":"aa", "y":"q","q":"ping", "a":{"id":"abcdefghij0123456789"}}
回覆包
r包含字段
包例子
{"t":"aa", "y":"r", "r":{"id":"mnopqrstuvwxyz123456"}}
請求包
a包含字段
包例子:
{"t":"aa", "y":"q","q":"find_node", "a":{"id":"abcdefghij0123456789","target":"mnopqrstuvwxyz123456"}}
回覆包
r包含字段
包例子
{"t":"aa", "y":"r", "r":{"id":"0123456789abcdefghij", "nodes":"def456..."}}
請求包
a包含字段
包例子
{"t":"aa", "y":"q","q":"get_peers", "a":{"id":"abcdefghij0123456789","info_hash":"mnopqrstuvwxyz123456"}}
回覆包
若是回覆者的路由表中,有存有info_hash資源的節點信息,就返回value,不然返回node,node的值和find_node同樣
r包含字段
包例子
{"t":"aa", "y":"r", "r":{"id":"abcdefghij0123456789", "token":"aoeusnth","values": ["axje.u", "idhtnm"]}}
請求包
a包含字段
包例子
{"t":"aa", "y":"q","q":"announce_peer", "a":{"id":"abcdefghij0123456789","info_hash":"mnopqrstuvwxyz123456", "port":6881, "token": "aoeusnth"}}
回覆包
r包含字段
包例子
{"t":"aa", "y":"r", "r":{"id":"mnopqrstuvwxyz123456"}}
e 列表類型,第一個元素時錯誤id,第二個是錯誤的說明
{"t":"aa", "y":"e", "e":[201,"A Generic Error Ocurred"]}
錯誤類型有:
向三個固定服務器發送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文件了
當獲得BT文件後,就能夠用bt文件下載器進行文件的下載
BT文件裏面包含
下載流程
因此bt文件的下載過程,並非去中心化的,tracket服務器就是一箇中心化的服務器。
tracket服務器只管理下載節點的信息,並不會存儲文件的具體分塊。因此壓力也比較小。
節點越多,下載的速度越快。
未經容許,請不要轉載