6 个版本 (稳定版)

2.0.8 2020 年 11 月 30 日
2.0.4 2020 年 11 月 25 日
2.0.1 2020 年 11 月 24 日
2.0.0 2020 年 11 月 23 日
0.1.1 2020 年 8 月 14 日

#1 in #punching


remote_shell 中使用

MIT 许可证

39KB
1K SLoC

UDP_HOLE_PUNCHING

这个 crate 旨在成为 rust p2p 通信框架。

什么是 p2p?

当一个套接字已经“连接”到另一个客户端时,“连接”是直接到客户端,而不是服务器。服务器不用于传递数据包,只是将两个客户端配对在一起。正如你所知,这正是 UDP 打洞 的全部目的。为了实现 p2p 框架,crate 提供了两个子函数

  • 服务器:如果你想要运行一个标准的等待客户端-被叫方发送注册标识的服务器,然后客户端-呼叫方发送带有客户端-被叫方 ID 的“请求”命令。服务器会将每个客户端的 IP 地址和外部端口号发送给对方。它还有一些基本的保护措施,比如防止超时等。如果你想有更多自定义选项,可以看看 make_match
  • 客户端(包括呼叫方和被叫方):在这个 crate 中,单个 udp 传输数据包的大小定义为“pub const Conf.size = 1024;”。然而,crate 会在发送时自动拆分超过大小限制的数据,在接收时会自动组装整合,在数据包不完整时请求重发。

快速入门

  • main.rs
    use async_std::task::block_on;
    pub mod server;
    pub mod client;
    #[macro_use]
    extern crate anyhow;
    use client::test::*;
    use server::process::test_swap_server;
    fn main() {

        // block_on(test_callee_listen());

        // block_on(test_caller_api());
        // block_on(test_swap_server());
    }


  • test_swap_server
    pub async fn test_swap_server() {
        let host = "0.0.0.0:xxxx";
        let res= make_match(host).await;
        match res{
            Ok(())=>dbg!("everything ok"),
            Err(e)=>dbg!(&e.to_string()),
        };
}
  • test_callee/caller_listen
 
fn read_file_as_u8(inputfile: &str) -> anyhow::Result<Vec<u8>> {
    let mut _inputfile = File::open(inputfile)?;
    let mut v: Vec<u8> = Vec::new();
    _inputfile.read_to_end(&mut v)?;
    Ok(v)
}

fn write_file_as_u8(path_str: &str, binary: &Vec<u8>) -> anyhow::Result<String> {
    let p = std::path::Path::new(path_str);
    std::fs::write(p, binary)?;
    Ok(format!("保存成功,地址:{}", path_str))
}


pub fn test_callee_listen() -> anyhow::Result<()> {
    let mut conf = Conf::default();
    conf.swap_server = "x.x.x.x:xxxx".to_string();
    conf.id = "xx".to_string();
    conf.db_path="./data/callee".to_string();
    conf.set();

    init_udp();
    std::thread::spawn(|| {
        listen();
    });
    loop {
        std::thread::sleep(Duration::from_secs(10));
        let (addr, v) = rec_from();
        if &v.len() > &0 {
            dbg!("callee rec res");
            write_file_as_u8("/home/b.exe", &v)?;
            let back = "callee got you".as_bytes().to_vec();
            send(&back, addr);
        }
    };
    Ok(())
}

pub fn test_caller_api() -> anyhow::Result<()> {
    let mut conf = Conf::default();
    conf.swap_server = "x.x.x.x:xxxx".to_string();
    conf.db_path="./data/caller".to_string();
    conf.set();
    init_udp();
    std::thread::spawn(|| {
        listen();
    });
    ask_peer_address("xx");
    std::thread::sleep(Duration::from_secs(9));
    let addr = read_peer_address()?;
    dbg!(&addr);
    dbg!("begin");

    let msg = read_file_as_u8("D://a.exe")?;
    let sess=send(&msg, addr);

    loop {
        let  v = rec_one(addr,sess);
        if v.len() > 0 {
            let s = String::from_utf8_lossy(&v);
            dbg!("caller  rec res");
        }
        std::thread::sleep(Duration::from_secs(4));
    }
    Ok(())
}


谁使用这个 crate?

依赖关系

~7–20MB
~249K SLoC