$> 实现一个Rust Unix Domain程序
背景
最近在用php写脚本时,对Unix Domain
这种IPC
进行了一些学习和使用。
我之后是打算利用Rust来实现一个存储服务,所以这次会对针对Rust的Unix Domain
使用进行了解,同时也会使用Rust来解一个二进制数据包。
Rust部分
1. 使用UnixListener
1 2
| let listen = UnixListener::bind("./helo.sock").unwrap();
|
2. 使用UnixStream
1 2 3 4 5 6 7 8 9 10 11 12
| for stream_pack in listen.incoming() { match stream_pack { Ok(mut stream) => { } Err(err) => { } } }
|
3. 使用包 ctrlc
控制 ctrl + c
信号
基于每次 UnixListener::bind()
时都不能存在 ./helo.sock
文件
1 2 3 4 5
| ctrlc::set_handler(move || { fs::remove_file("./helo.sock").unwrap(); process::exit(0); }).unwrap();
|
4. 读取请求流中的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Ok(stream) => { thread::spawn(move || { handle_client(stream); }); }
fn handle_client(mut stream: UnixStream) { let mut rec_msg = String::new(); stream.read_to_string(&mut rec_msg).unwrap(); println!("{}", rec_msg); }
|
5. 请求流中的结构化数据
网络请求中的数据往往是二进制数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
#[derive(Debug)] struct Pmsg { len: i32, msg: Vec<u8>, msg_str: String, }
impl Pmsg { pub fn new(len: i32, msg: &[u8]) -> Self { let mut imsg: Vec<u8> = vec![0;len as usize]; imsg.clone_from_slice(msg); let smsg = std::str::from_utf8(msg).unwrap().to_string(); Pmsg { len, msg: imsg, msg_str: smsg, } }
pub fn build_len(rec_d: &[u8]) -> i32 { let mut hnum: Vec<u8> = vec![0, 0, 0, 0];
hnum.clone_from_slice(rec_d);
hnum.reverse();
let hlen = unsafe { *(hnum.as_ptr() as *const i32) };
return hlen; } }
fn handle_client(mut stream: UnixStream) { let mut rec_msg = Vec::new(); stream.read_to_end(&mut rec_msg).unwrap(); let plen = Pmsg::build_len(&rec_msg[..=3]); let pmsg_result = Pmsg::new(plen, &rec_msg[4..]); println!("{:?}", pmsg_result); }
|
PHP部分
实现一个简单unix domain client
1 2 3 4 5 6 7 8 9 10
| $sock = socket_create(AF_UNIX, SOCK_STREAM, 0); socket_connect($sock, './helo.sock');
$msg = 'hello fq'; $premsg = strlen($msg);
$pmsg = pack('N1a*', $premsg, $msg); socket_write($sock, $pmsg);
|