You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.9 KiB
119 lines
3.9 KiB
use std::io; |
|
use std::path::Path; |
|
use std::str::FromStr; |
|
|
|
use bigdecimal::BigDecimal; |
|
use tokio::io::AsyncReadExt; |
|
use tokio::io::AsyncWriteExt; |
|
use tokio::io::Interest; |
|
use tokio::net::UnixListener; |
|
use tokio::net::UnixStream; |
|
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)] |
|
enum Message { |
|
First(i64, String), |
|
Second(i64, Option<String>), |
|
Third(i64), |
|
Fourth(BigDecimal), |
|
} |
|
|
|
#[tokio::main(flavor = "current_thread")] |
|
async fn main() { |
|
let path = Path::new("./comm.socket"); |
|
let _ = std::fs::remove_file(&path); |
|
|
|
// producer |
|
let path_prod = path.to_path_buf(); |
|
let producer = tokio::spawn(async move { |
|
let listener = UnixListener::bind(&path_prod).unwrap(); |
|
loop { |
|
match listener.accept().await { |
|
Ok((mut stream, _addr)) => { |
|
println!("Client here"); |
|
tokio::spawn(async move { send_to_consumer(&mut stream).await }) |
|
} |
|
Err(e) => { |
|
println!("Erro! {:?}", e); |
|
break; |
|
} |
|
}; |
|
} |
|
}); |
|
|
|
// consumer |
|
let path_cons = path.to_path_buf(); |
|
let consumer = tokio::spawn(async move { |
|
let mut socket = UnixStream::connect(&path_cons).await.unwrap(); |
|
loop { |
|
let ready = socket.ready(Interest::READABLE).await.unwrap(); |
|
if ready.is_readable() { |
|
let size = socket.read_u64().await.unwrap(); |
|
println!("Content length: {}", size as usize); |
|
|
|
let mut record = vec![0u8; size as usize]; |
|
loop { |
|
match socket.read_exact(&mut record).await { |
|
Ok(0) => { |
|
tokio::task::yield_now().await; |
|
continue; |
|
} |
|
Ok(n) => { |
|
println!("Read {} bytes: {:?}", n, record); |
|
let message: Result<Message, Box<bincode::ErrorKind>> = |
|
bincode::deserialize(&record); |
|
match message { |
|
Ok(the_message) => println!("Message: {:?}", the_message), |
|
Err(e) => println!("Deserialized message: {:?}", e), |
|
} |
|
break; |
|
} |
|
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { |
|
break; |
|
} |
|
Err(e) => { |
|
println!("Read error: {:?}", e); |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
}); |
|
|
|
// and... WAIT! |
|
let _ = tokio::join!(producer, consumer); |
|
} |
|
|
|
async fn send_to_consumer(stream: &mut UnixStream) { |
|
let mut should_yield = false; |
|
let mut seq = 0; |
|
loop { |
|
let message = match seq % 5 { |
|
0 => Message::First(seq, format!("{} first", seq)), |
|
1 => Message::Second(seq, Some(format!("{} second", seq))), |
|
2 => Message::Third(seq), |
|
_ => Message::Fourth(BigDecimal::from_str(&format!("{}", seq)).unwrap()), |
|
}; |
|
seq += 1; |
|
|
|
let encoded = bincode::serialize(&message).unwrap(); |
|
let len = encoded.len(); |
|
|
|
let ready = stream.ready(Interest::WRITABLE).await.unwrap(); |
|
if ready.is_writable() { |
|
// Header, with the size |
|
stream.write_u64(len as u64).await.unwrap(); |
|
|
|
// The content |
|
match stream.try_write(&encoded) { |
|
Ok(n) => println!("Wrote {} bytes: {:?}", n, encoded), |
|
Err(e) => println!("Write error: {:?}", e), |
|
} |
|
|
|
should_yield = !should_yield; |
|
if should_yield { |
|
tokio::task::yield_now().await; |
|
} |
|
} |
|
} |
|
}
|
|
|