libp2p-rs v0.2.0已經支持Kad-DHT,支持節點經過DHT網絡發現節點和內容。
本文主要展現如何在libp2p-rs使用DHT,以及羅列出swarm和kad的部分API。node
let sec = secio::Config::new(keys.clone()); let mux = yamux::Config::new(); let tu = TransportUpgrade::new(TcpConfig::default(), mux, sec); let mut swarm = Swarm::new(keys.public()) .with_transport(Box::new(tu)) .with_identify(IdentifyConfig::new(false)); swarm.listen_on(vec![listen_addr]).expect("listen on"); let mut swarm_control = swarm.control();
let store = MemoryStore::new(swarm.local_peer_id().clone()); let kad = Kademlia::new(swarm.local_peer_id().clone(), store); let kad_handler = kad.handler(); let mut kad_ctrl = kad.control();
將swarm升級,使其具有routing功能。git
// register handler to swarm swarm = swarm.with_protocol(Box::new(kad_handler)).with_routing(Box::new(kad_ctrl.clone()));
kad.start(swarm_control.clone()); swarm.start();
先將bootstrap節點添加到peerstore和路由表,再啓動bootstrap。github
kad_control.add_node(bootstrap_peer, vec![bootstrap_addr]).await; kad_control.bootstrap().await;
集成cli,可調試swarm和kad。bootstrap
let mut app = App::new("xCLI").version("v0.1").author("kingwel.xie@139.com"); app.add_subcommand_with_userdata(swarm_cli_commands(), Box::new(swarm_control.clone())); app.add_subcommand_with_userdata(dht_cli_commands(), Box::new(kad_control.clone())); app.run();
如下只列出部分經常使用的調試命令,更多玩法請親自下場解鎖。安全
connection命令能夠用於獲取當前全部鏈接及其子流的信息,也能夠獲取和某個peer的鏈接信息。bash
# s con CID DIR Remote-Peer-Id I/O Remote-Multiaddr 231 In Qmf3ZX3yHnmzaXFGH5G149HyrAeKRFantVnZ9gZdnuPv1U 2/0 /ip4/114.227.83.230/tcp/24792 (231 Sid(7) In /ipfs/kad/1.0.0) (231 Sid(9) In /ipfs/kad/1.0.0) 161 In QmZC9dZPyJWXSB2Ao2ChGJMjfuFiT7TyKdsGsFEKVSqnnf 0/0 /ip4/212.102.37.201/tcp/4001 2185 In QmTmnqSEarcSLJxhehJRKX64pxSkeKn7jS2fDEZFjjt9Bn 1/0 /ip4/114.226.44.86/tcp/3109 (2185 Sid(7) In /ipfs/kad/1.0.0) 2069 In 12D3KooWPtfLkqAVMPP6FNufHvqxPYe55XuAdEZWUn2cPbLLAwuT 1/0 /ip4/111.16.39.80/tcp/17881 (2069 Sid(1) In /ipfs/kad/1.0.0) 2349 In QmVcXP4bnoCJkUUJinduuM68n5jfSjDj6sKaTjRhHoecpt 1/0 /ip4/83.248.150.24/tcp/42761 (2349 Sid(3) In /ipfs/kad/1.0.0) 492 In 12D3KooWKBkFNUCvyP5PbV2mAhrzcvPi4EPL4vD3CjieGGU9ZcQr 1/0 /ip4/203.145.95.60/tcp/64417 (492 Sid(1) In /ipfs/kad/1.0.0) 18 In QmP6waLA8S6M8WPoQ5tWPE6xpgtsJ44LGQcq7vDTUAmyob 1/0 /ip4/188.127.190.220/tcp/4001 (18 Sid(7) In /ipfs/kad/1.0.0) # s con Qmf3ZX3yHnmzaXFGH5G149HyrAeKRFantVnZ9gZdnuPv1U CID DIR Remote-Peer-Id I/O Remote-Multiaddr 231 In Qmf3ZX3yHnmzaXFGH5G149HyrAeKRFantVnZ9gZdnuPv1U 2/0 /ip4/114.227.83.230/tcp/24792 (231 Sid(7) In /ipfs/kad/1.0.0) (231 Sid(9) In /ipfs/kad/1.0.0)
states用於統計迭代查詢運行情況,也能夠觀察當前節點接收到的Kad請求的次數。網絡
# d st Total refreshes : 1 Successful queries : 4 Timeout queries : 0 Query details : QueryStats { requests: 59, success: 41, failure: 10, duration: 18.198653932s } Kad rx messages : MessageStats { ping: 0, find_node: 17216, get_provider: 559, add_provider: 3667, get_value: 1, put_value: 27 }
dump命令用於dump出路由表的信息,使用verbose能夠打印詳細信息。app
# d dp Index Entries Active 244 1 1 246 1 1 247 2 2 248 7 7 249 10 8 250 20 20 251 20 20 252 20 20 253 20 20 254 20 19 255 20 20 # d dp 1 Index Entries Active 244 1 1 Qme9PR5oDcSSGoS2He53RqaML4vinDD5CNgxxmV2qPefFP Conn(false) Some(52292.68894773s) Addrs([]) 246 1 1 QmboRZYso6VdQ5yfXe1DAj9u8EqouZGUsf2inoqYDtzdf8 Conn(true) Some(4330.367016609s) Addrs([]) 247 2 2 QmZsbivLpaVpWQ4Mum2nzbEcoXbH7QbftRkQCmmJiTqcUp Conn(false) Some(77688.875853187s) Addrs([]) QmZaCQ6anyaPuebhLeomzpyKRAY6GnNS5NCU8h7kSjwFKN Conn(false) Some(43775.12096365s) Addrs(["/ip4/127.0.0.1/tcp/4001", "/ip4/138.68.29.104/tcp/4001", "/ip4/10.46.0.6/tcp/4001", "/ip4/10.138.16.85/tcp/4001", "/ip6/::1/tcp/4001"])
目前swarm和kad的API已經比較完善,如下只列出部分經常使用的API,想了解更多API請直接閱讀源碼。async
/// Gets the public key by peer_id. pub fn get_key(&self, peer_id: &PeerId) -> Option<PublicKey> /// Gets all multiaddr of a peer. pub fn get_addrs(&self, peer_id: &PeerId) -> Option<Vec<Multiaddr>> /// Adds a address to address_book by peer_id, if exists, update rtt. pub fn add_addr(&self, peer_id: &PeerId, addr: Multiaddr, ttl: Duration) /// Adds many new addresses if they're not already in the peer store. pub fn add_addrs(&self, peer_id: &PeerId, addrs: Vec<Multiaddr>, ttl: Duration) /// Clears all multiaddr of a peer from the peer store. pub fn clear_addrs(&self, peer_id: &PeerId)
/// Make a new connection towards the remote peer with addresses specified. pub async fn connect_with_addrs(&mut self, peer_id: PeerId, addrs: Vec<Multiaddr>) -> Result<()> /// Make a new connection towards the remote peer. /// /// It will lookup the peer store for address of the peer, otherwise /// initiate the routing interface for querying the addresses, if routing /// is available. pub async fn new_connection(&mut self, peer_id: PeerId) -> Result<()> /// Make a new connection towards the remote peer, without using routing(Kad-DHT). pub async fn new_connection_no_routing(&mut self, peer_id: PeerId) -> Result<()> /// Close connection towards the remote peer. pub async fn disconnect(&mut self, peer_id: PeerId) -> Result<()>
/// Open a new outbound stream towards the remote peer. /// /// It will lookup the peer store for address of the peer, /// otherwise initiate the routing interface for address querying, /// when routing is enabled. In the end, it will open an outgoing /// sub-stream when the connection is eventually established. pub async fn new_stream(&mut self, peer_id: PeerId, pids: Vec<ProtocolId>) -> Result<Substream> /// Open a new outbound stream towards the remote peer, without routing. pub async fn new_stream_no_routing(&mut self, peer_id: PeerId, pids: Vec<ProtocolId>) -> Result<Substream> /// Open a new outbound stream towards the remote peer, without routing. pub async fn new_stream_no_routing(&mut self, peer_id: PeerId, pids: Vec<ProtocolId>) -> Result<Substream>
/// Add a node and its listening addresses to KBuckets. pub async fn add_node(&mut self, peer_id: PeerId, addrs: Vec<Multiaddr>) /// Add a node and its listening addresses to KBuckets. pub async fn remove_node(&mut self, peer_id: PeerId) /// Initiate bootstrapping. /// /// In general it should be done only once upon Kad startup. pub async fn bootstrap(&mut self) /// Lookup the closer peers with the given key. pub async fn lookup(&mut self, key: record::Key) -> Result<Vec<KadPeer>> /// Lookup the given peer. pub async fn find_peer(&mut self, peer_id: &PeerId) -> Result<KadPeer> /// Put value in local and other peers which closest to the given key. pub async fn put_value(&mut self, key: Vec<u8>, value: Vec<u8>) -> Result<()> /// Get value from local and other peers which closest to the given key. pub async fn get_value(&mut self, key: Vec<u8>) -> Result<Vec<u8>> /// Announce to peers which closer to the given key that self provide content. pub async fn provide(&mut self, key: Vec<u8>) -> Result<()> /// Find peers who provide content. pub async fn find_providers(&mut self, key: Vec<u8>, count: usize) -> Option<Vec<KadPeer>>
在啓動kad和swarm後,就能夠經過句柄(controller),調用API。當前
swarm的API已經比較完善,目前已經能夠支持Kad-DHT這種比較複雜的協議,這也爲新協議的添加創造了條件。tcp
Netwarps 由國內資深的雲計算和分佈式技術開發團隊組成,該團隊在金融、電力、通訊及互聯網行業有很是豐富的落地經驗。Netwarps 目前在深圳、北京均設立了研發中心,團隊規模30+,其中大部分爲具有十年以上開發經驗的技術人員,分別來自互聯網、金融、雲計算、區塊鏈以及科研機構等專業領域。Netwarps 專一於安全存儲技術產品的研發與應用,主要產品有去中心化文件系統(DFS)、去中心化計算平臺(DCP),致力於提供基於去中心化網絡技術實現的分佈式存儲和分佈式計算平臺,具備高可用、低功耗和低網絡的技術特色,適用於物聯網、工業互聯網等場景。公衆號:Netwarps