use quickring::RingBuffer;
use std::net::UdpSocket;
use std::thread;
use std::time::Duration;
fn main() -> std::io::Result<()> {
let server_thread = run_udp_server();
let client_thread = run_udp_client();
let _ = server_thread.join();
let _ = client_thread.join();
Ok(())
}
fn run_udp_server() -> thread::JoinHandle<()> {
thread::spawn(|| {
let socket = UdpSocket::bind("127.0.0.1:9000").expect("Server bind failed");
println!("Server listening on 127.0.0.1:9000");
let mut buf = [0u8; 1024];
let (n, client_addr) = socket.recv_from(&mut buf).expect("recv_from failed");
println!("Server: client connected from {}", client_addr);
println!("Server received initial packet: {:?}", &buf[..n]);
let mut counter = 0;
loop {
let msg = format!("packet {}\n", counter);
socket
.send_to(msg.as_bytes(), client_addr)
.expect("send_to failed");
counter += 1;
thread::sleep(Duration::from_millis(100));
}
})
}
fn run_udp_client() -> thread::JoinHandle<()> {
thread::spawn(|| {
let socket = UdpSocket::bind("127.0.0.1:0").expect("Client bind failed");
socket
.connect("127.0.0.1:9000")
.expect("Client connect failed");
socket.send(b"hello").expect("Initial send failed");
const CAPACITY: usize = 1 << 13;
let rb = RingBuffer::<Vec<u8>, CAPACITY>::new();
let (mut prod, mut cons) = rb.split();
let recv_thread = thread::spawn(move || {
let mut buf = [0u8; 2048];
loop {
match socket.recv(&mut buf) {
Ok(n) => {
let packet = buf[..n].to_vec();
if !prod.push(packet) {
eprintln!("Ring buffer full, dropping packet");
}
}
Err(e) => {
eprintln!("recv error: {}", e);
break;
}
}
}
});
loop {
if let Some(packet) = cons.pop() {
let text = String::from_utf8_lossy(&packet);
print!("Client got: {}", text);
} else {
std::thread::yield_now();
}
}
let _ = recv_thread.join();
})
}