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 中使用
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?
- remote_shell: https://github.com/wangmarkqi/remote_shell
依赖关系
~7–20MB
~249K SLoC