diff --git a/udp_laminar/udp_server_client/Cargo.lock b/udp_laminar/udp_server_client/Cargo.lock new file mode 100644 index 0000000..f5a0ea1 --- /dev/null +++ b/udp_laminar/udp_server_client/Cargo.lock @@ -0,0 +1,163 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +dependencies = [ + "cfg-if", + "lazy_static", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "laminar" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96f75f071a80952498ac17613843a2f529188ac053af7d358403aac4e34551" +dependencies = [ + "byteorder", + "crc", + "crossbeam-channel", + "lazy_static", + "log", + "rand", + "rand_pcg", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" + +[[package]] +name = "log" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom", + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core", +] + +[[package]] +name = "udp_server_client" +version = "0.1.0" +dependencies = [ + "laminar", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" diff --git a/udp_laminar/udp_server_client/Cargo.toml b/udp_laminar/udp_server_client/Cargo.toml new file mode 100644 index 0000000..22d24e0 --- /dev/null +++ b/udp_laminar/udp_server_client/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "udp_server_client" +version = "0.1.0" +authors = ["Hatter Jiang "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +laminar = "0.3" + diff --git a/udp_laminar/udp_server_client/src/main.rs b/udp_laminar/udp_server_client/src/main.rs new file mode 100644 index 0000000..3d47793 --- /dev/null +++ b/udp_laminar/udp_server_client/src/main.rs @@ -0,0 +1,109 @@ +//! Note that the terms "client" and "server" here are purely what we logically associate with them. +//! Technically, they both work the same. +//! Note that in practice you don't want to implement a chat client using UDP. +use std::io::stdin; +use std::thread; +use std::time::Instant; + +use laminar::{ErrorKind, Packet, Socket, SocketEvent}; + +const SERVER: &str = "127.0.0.1:12351"; + +fn server() -> Result<(), ErrorKind> { + let mut socket = Socket::bind(SERVER)?; + let (sender, receiver) = (socket.get_packet_sender(), socket.get_event_receiver()); + let _thread = thread::spawn(move || socket.start_polling()); + + loop { + if let Ok(event) = receiver.recv() { + match event { + SocketEvent::Packet(packet) => { + let msg = packet.payload(); + + if msg == b"Bye!" { + break; + } + + let msg = String::from_utf8_lossy(msg); + let ip = packet.addr().ip(); + + println!("Received {:?} from {:?}", msg, ip); + + sender + .send(Packet::reliable_unordered( + packet.addr(), + "Copy that!".as_bytes().to_vec(), + )) + .expect("This should send"); + } + SocketEvent::Timeout(address) => { + println!("Client timed out: {}", address); + } + _ => {} + } + } + } + + Ok(()) +} + +fn client() -> Result<(), ErrorKind> { + let addr = "127.0.0.1:12352"; + let mut socket = Socket::bind(addr)?; + println!("Connected on {}", addr); + + let server = SERVER.parse().unwrap(); + + println!("Type a message and press Enter to send. Send `Bye!` to quit."); + + let stdin = stdin(); + let mut s_buffer = String::new(); + + loop { + s_buffer.clear(); + stdin.read_line(&mut s_buffer)?; + let line = s_buffer.replace(|x| x == '\n' || x == '\r', ""); + + socket.send(Packet::reliable_unordered( + server, + line.clone().into_bytes(), + ))?; + + socket.manual_poll(Instant::now()); + + if line == "Bye!" { + break; + } + + match socket.recv() { + Some(SocketEvent::Packet(packet)) => { + if packet.addr() == server { + println!("Server sent: {}", String::from_utf8_lossy(packet.payload())); + } else { + println!("Unknown sender."); + } + } + Some(SocketEvent::Timeout(_)) => {} + _ => println!("Silence.."), + } + } + + Ok(()) +} + +fn main() -> Result<(), ErrorKind> { + let stdin = stdin(); + + println!("Please type in `server` or `client`."); + + let mut s = String::new(); + stdin.read_line(&mut s)?; + + if s.starts_with("s") { + println!("Starting server.."); + server() + } else { + println!("Starting client.."); + client() + } +}