bt协议详解 DHT篇(上)
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分鐘之內沒有活動的話,這個節點變成問題節點。當一個節點響應請求失敗的話,它就變成壞的節點?;钴S的節點比狀態不明的節點的優先級要高(這不是顯然嗎?)。
路由表覆蓋從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的聯系信息加入到路由表中。
本文來自 免費教程網
轉載于:https://my.oschina.net/ideras/blog/689669
總結
以上是生活随笔為你收集整理的bt协议详解 DHT篇(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言同余法随机数,线性同余法取随机数
- 下一篇: ffmpeg 推流