前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >libp2p之mdns简单使用

libp2p之mdns简单使用

原创
作者头像
8菠萝
修改2023-09-28 15:45:26
4780
修改2023-09-28 15:45:26
举报
文章被收录于专栏:菠萝上市没有菠萝上市没有

背景

由于github老被墙,原来使用github备份/同步文档效率太低了, 打算写一个局域网内多端文件自动同步的小工具。其中有个环节需要结点之间能自动发现局域网其他结点。所以打算使用mdns现实服务自动发现的功能。

实现

Cargo.toml

代码语言:text
复制
[package]  
name = "airsync"  
version = "0.1.0"  
edition = "2021"  
  
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html  
  
[dependencies]  
async-std = { version = "1.12", features = ["attributes"] }  
async-trait = "0.1"  
env_logger = "0.10.0"  
futures = "0.3.28"  
chrono = "0.4"  
serde = { version = "1.0", features = ["derive"] }  
libp2p = { version = "0.52", features = [  
    "async-std",  
    "mdns",  
    "tokio",  
    "noise",  
    "macros",  
    "tcp",  
    "yamux",  
    "quic",  
    "cbor",  
    "request-response",  
] }

main.rs

代码语言:txt
复制
use std::{error::Error};  
  
use futures::future::Either;  
use futures::StreamExt;  
use libp2p::{core::upgrade::Version, identity, noise, swarm::{SwarmBuilder, SwarmEvent}, tcp, yamux, PeerId, Transport, Multiaddr, mdns, quic, request_response, StreamProtocol};  
use libp2p::core::muxing::StreamMuxerBox;  
use libp2p::core::transport::OrTransport;  
use libp2p::request_response::{Message, ProtocolSupport};  
use libp2p::swarm::NetworkBehaviour;  
use serde::{Deserialize, Serialize};  
  
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]  
struct FileRequest(String);  
  
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]  
pub(crate) struct FileResponse(Vec<u8>);  
  
#[derive(NetworkBehaviour)]  
struct NodeBehaviour {  
    mdns: mdns::async_io::Behaviour,     // 结点发现  
    handler: request_response::cbor::Behaviour<FileRequest, FileResponse>,  // 数据传输  
    keep_live: libp2p::swarm::keep_alive::Behaviour,    // 心跳  
}  
  
  
#[async_std::main]  
async fn main() -> Result<(), Box<dyn Error>> {  
    env_logger::init();  
	// key
    let local_key = identity::Keypair::generate_ed25519();  
    let local_peer_id = PeerId::from(local_key.public());  

    let tcp_transport = tcp::async_io::Transport::new(tcp::Config::default().nodelay(true))  
        .upgrade(Version::V1Lazy)  
        .authenticate(noise::Config::new(&local_key).unwrap())  
        .multiplex(yamux::Config::default())  
        .boxed();  
  
    let quic_transport = quic::async_std::Transport::new(quic::Config::new(&local_key));  
    let transport = OrTransport::new(quic_transport, tcp_transport)  
        .map(|either_output, _| match either_output {  
            Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),  
            Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),  
        })  
        .boxed();  
  
    let mdns = mdns::async_io::Behaviour::new(mdns::Config::default(), local_peer_id).unwrap();  
    let request_handler = request_response::cbor::Behaviour::new([(StreamProtocol::new("/file-exchange/1"), ProtocolSupport::Full, )], request_response::Config::default());  
    let behaviour = NodeBehaviour { mdns, handler: request_handler, keep_live: libp2p::swarm::keep_alive::Behaviour::default() };  
  
    let mut swarm = SwarmBuilder::with_async_std_executor(transport, behaviour, local_peer_id).build();  
    swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;  
    swarm.listen_on("/ip4/0.0.0.0/udp/0/quic-v1".parse()?)?;  
  
    loop {  
        match swarm.select_next_some().await {  
            SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"),  
            SwarmEvent::Behaviour(NodeBehaviourEvent::Mdns(mdns::Event::Discovered(list))) => {  
                for peer in list {  
                    let mut peer_id = peer.0;  
                    println!("mDNS discovered a new peer: {peer_id}");  
  
                    // 测试发用文本  
                    let req = { "Hi".to_string() };  
                    swarm.behaviour_mut().handler.send_request(&mut peer_id, FileRequest(req));  
                }  
            }  
            SwarmEvent::Behaviour(NodeBehaviourEvent::Mdns(mdns::Event::Expired(list))) => {  
                for peer in list {  
                    let peer_id = peer.0;  
                    println!("mDNS discover peer has expired: {peer_id}");  
                }  
            }  
            SwarmEvent::Behaviour(NodeBehaviourEvent::Handler(request_response::Event::Message { message, .. }, )) => {  
                match message {  
                    Message::Request { request, channel, .. } => {  
                        println!("Message:{:?}", request);  
                    }  
                    Message::Response {request_id, response}=>{  
                    }  
                }  
            }  
            _ => {}  
        }  
    }  
}

结果

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 实现
  • 结果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档