首頁  >  文章  >  Java  >  如何用java實作一個p2p種子搜尋的功能

如何用java實作一個p2p種子搜尋的功能

不言
不言轉載
2019-04-15 10:20:393985瀏覽

本篇文章帶給大家的內容是關於如何用java實現一個p2p種子搜尋的功能,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

很多年前對p2p就有很大的興趣,不過都是停留在理論上,一直沒有機會去真正的實踐。最近把這個東西實現了一下,從剛開始入手到現在,我覺得有些東西可以分享。進入正題吧那就

基本概念

再講p2p之前,我想先講一下我們是如何進行下載檔的。我列舉一下幾種文件下載的方式

1.使用http協議下載,使用的最多的可能就是透過瀏覽器進行文件的下載。

2.使用ftp下載,ftp有兩種模式,一種是port(主動)模式,這種模式用戶端會在本地開啟一個端口N(>1023)建立ftp連接,然後發送給ftp伺服器N 1監聽埠用來資料傳輸,當有防火牆或客戶端被nat的情況下就無法下載。另外一種方式是被動模式(passive),這種模式ftp服務端除了21端口以外會開啟一個另外大於1023的端口,也就是說客戶端會主動發起ftp連接和數據傳輸連接,只要ftp伺服器開放了這個端口那就不會有問題。

上面兩種方式可以統稱為cs架構,這種架構下面,資源都集中在服務端,當資料量大到一定程度的時候就會出現問題。為了解決這個問題,我們可能會想到分散式去中心化,於是p2p應運而生,p2p即 peer to peer,這是一種對等架構,每個節點既是客服端又是服務端。

p2p架構

當把資源都儲存在每個節點上面的時候,我們可能會想,當我下載一個資源的時候,那我怎麼知道這個檔案在那些機器上面能下載呢?

早期的p2p架構中存在一個tracker的角色,這個tracker負責儲存檔案的元資料資訊。那麼現在檔案會保存在每個peer上面,然後透過tracker取得檔案資訊。

這種架構下面我們所有的文件都分佈式了,只是tracker會負責存儲所有文件的元數據信息,所以tracker只需要存儲少量數據,相對於存在文件會相對輕鬆很多了。

但是一旦出現tracker伺服器掛了或服務不可用那麼就會導致所有的檔案都無法下載,因為它還沒有完全的分散式,為了完全的去中心化,後面出來一種trackerless架構,

這時候不在存在tracker這個東西,所有的檔案包含檔案的元資料資訊都分散式儲存。

DHT

DHT(Distributed Hash Table)分散式雜湊表,它是用來取代tracker。實作dht的演算法很多,例如Kademlia演算法等等。
幾個概念:

1.nodeid 在dht網路中每個nodeid都是160bit

2.XOR 兩個節點之間的距離使用異或來計算

3.routting table路由表

這裡的話還是主要講實現所以原理這部分的話網上也有很多資料大家可以參考看看

#如何實現

實現種子搜尋分為兩步,第一步是爬蟲,用來爬取網上的種子信息,第二步是加入搜尋。

需要具備以下知識:種子,bittorrent dht 協議,bencoded

提到p2p不得不提種子,就是那種.torrent結果的那種文件,大家可能都是用過bt種子下載過文件,下載文件使用的是bittorrent協定。那麼要如何收集網路上面的種子呢?

bt種子包含的主要欄位:戳:https://segmentfault.com/a/1190000000681331

在dht中取得的種子叫trackerless torrent,沒有announce這個屬性,但會有nodes屬性來代替。官方建議不要router.bittorrent.com把這個加到種子裡面,不要加到路由表。

1.如何從dht中獲取種子

如果想要得到種子信息,那麼必須要對DHT Protocol深入了解,bep_0005描述了DHT Protocol

具體可以戳這裡http://www.bittorrent.org/beps/bep_0005.html

如何實作一個路由表:

路由表覆蓋了所有Node的id,從0到2的160次方。路由表可以由bucket組成,每個bucket都涵蓋了所有node的一部分。

剛開始一個路由表只有一個bucket,覆蓋了所有的nodeid。每個bucket,只能hold最多K個nodes,目前這個K值是8。如果bucket已經滿了,而且裡面的node都是好的,而且自身的nodeid不在這個bucket裡面,那麼就講原來的bucket分成兩個新的bucket,分別覆蓋0..2159和2159..2160

當一個bucket已經滿了的時候,新node很容易被丟棄,如果這裡面的node掉線了,那麼就會被replace。如果一個節點最近15分鐘都沒有ping過,那就對這個節點發起ping,如果沒有回傳response,那麼這個節點也會被replace。

每一個bucket應該有一個last changed屬性,用來表示這個bucket的活躍度。這幾種情況會更新這個字段:

1.bucket裡面的node被ping了並且有response

2.一個node加到了這個bucket裡面

3. bucket裡面的node被replace了

bucket在15分鐘內沒有更新這個字段的話,那麼就會隨機選取一個在該bucket範圍內的id,做find_node操作。

KRPC Protocol

dht網路中透過KRPC Protocol來傳遞訊息。

1.ping

ping查詢主要用來心跳檢查

2.find_node

查找一個節點,對方會從自己的路由表中查詢最近的N個節點返回,一般是8個

#3.get_peers

##根據infohash查找擁有該infohash的peer,如果查到返回peers,沒有查找到返回nodes

4.announce_peer

告訴其他的peers,自己也擁有infohash。

注意以上四個都會刷新路由表

#一開始路由表裡面沒有任何節點,所以需要從超級節點(例如

dht.transmissionbt.com等等)透過find_node請求來尋找並新增節點,返回的節點在進行find_node。

我自己實作的路由表稍微和上面描述的不太一樣。

dht網路中採用udp進行資料傳輸,所以我只用開啟一個upd埠不斷的發送find_node請求建立路由表,然後透過get_peers和announce_peer來取得種子的infohash。

當我們加入dht網路後,透過上面介紹的四個方法只能得到種子檔案的infohash,所以我們還需要透過infohash來下載種子,具體可以參考bep_009http:/ /www.bittorrent.org/beps/bep_0009.html

我們主要透過bep_009來取得種子的名字字段,取得了檔案名稱段就可以根據名字和infohash來建立索引提供搜尋。 (

這裡主要建立磁力鏈接,有了磁力鏈接就可以去迅雷,百度網盤等去下載資源啦

大部分磁力鏈接格式:magnet:?xt=urn: btih:infohash

上面介紹的方式是透過取得infohash來建立磁力鏈接,再藉助第三方軟體下載,當然也可以自己透過BitTorrent Protocol來下載,有興趣的可以自行研究。

好了,上面只是簡單的介紹了一些實現的步驟,很多細節和具體實現的話沒有提到,我自己的話,參考了一些github dht的項目,然後自己實現了一下具體地址如下:https://github.com/mistletoe9527/dht-spider

以上是如何用java實作一個p2p種子搜尋的功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除