From 7c6189234481cc6be1e6495427f0c9931167812f Mon Sep 17 00:00:00 2001 From: harsh_jain Date: Thu, 11 Oct 2018 16:19:50 +0530 Subject: [PATCH] socket chat in rust --- .gitignore | 1 + rust/Cargo.lock | 14 ++++++++ rust/Cargo.toml | 7 ++++ rust/README.md | 27 ++++++++++++++++ rust/src/main.rs | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 .gitignore create mode 100644 rust/Cargo.lock create mode 100644 rust/Cargo.toml create mode 100644 rust/README.md create mode 100644 rust/src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a54eab --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +rust/target diff --git a/rust/Cargo.lock b/rust/Cargo.lock new file mode 100644 index 0000000..f370060 --- /dev/null +++ b/rust/Cargo.lock @@ -0,0 +1,14 @@ +[[package]] +name = "bufstream" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "socket-server-test" +version = "0.1.0" +dependencies = [ + "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 0000000..6379dbf --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "socket-server-test" +version = "0.1.0" +authors = ["Clemens Wallrath "] + +[dependencies] +bufstream = "0.1" diff --git a/rust/README.md b/rust/README.md new file mode 100644 index 0000000..ce08d29 --- /dev/null +++ b/rust/README.md @@ -0,0 +1,27 @@ +# Socket Chat Server in Rust + +## Prerequisite +``` +curl -sSf https://static.rust-lang.org/rustup.sh | sh +``` +Cargo installation # package manager for rust # https://doc.rust-lang.org/cargo/getting-started/installation.html + +## Run + +Start server -- +``` +cargo run +``` + +Server is running at port 8888. + +Connect Client, using swissy-army knife -- +``` +nc localhost 8888 +``` + + +## References + +- https://nbaksalyar.github.io/2015/07/10/writing-chat-in-rust.html +- https://gist.github.com/andelf/8668088 diff --git a/rust/src/main.rs b/rust/src/main.rs new file mode 100644 index 0000000..4617434 --- /dev/null +++ b/rust/src/main.rs @@ -0,0 +1,83 @@ +extern crate bufstream; + +use std::str::FromStr; +use std::io::Write; +use std::net::{TcpListener, TcpStream}; +use std::net::SocketAddr; +use std::thread::spawn; +use bufstream::BufStream; +use std::io::BufRead; +use std::sync::{Arc,RwLock}; +use std::sync::mpsc; +use std::sync::mpsc::{Sender, Receiver}; + +fn handle_connection(stream: &mut BufStream, chan: Sender, arc: Arc>>) { + stream.write(b"Welcome to Simple Chat Server!\n").unwrap(); + stream.write(b"Plz input yourname: ").unwrap(); + stream.flush().unwrap(); + let mut name = String::new(); + stream.read_line(&mut name).unwrap(); + let name = name.trim_right(); + stream.write_fmt(format_args!("Hello, {}!\n", name)).unwrap(); + stream.flush().unwrap(); + + let mut pos = 0; + loop { + { + let lines = arc.read().unwrap(); + println!("DEBUG arc.read() => {:?}", lines); + for i in pos..lines.len() { + stream.write_fmt(format_args!("{}", lines[i])).unwrap(); + pos = lines.len(); + }; + } + stream.write(b" > ").unwrap(); + stream.flush().unwrap(); + + let mut reads = String::new(); + stream.read_line(&mut reads).unwrap(); //TODO: non-blocking read + if reads.trim().len() != 0 { + println!("DEBUG: reads len =>>>>> {}", reads.len()); + chan.send(format!("[{}] said: {}", name, reads)).unwrap(); + println!("DEBUG: got '{}' from {}", reads.trim(), name); + } + } +} + +fn main() { + let addr: SocketAddr = SocketAddr::from_str("127.0.0.1:8888").unwrap(); + let listener = TcpListener::bind(addr).unwrap(); + + let (send, recv): (Sender, Receiver) = mpsc::channel(); + let arc: Arc>> = Arc::new(RwLock::new(Vec::new())); + + let arc_w = arc.clone(); + + spawn(move|| { + loop { + let msg = recv.recv().unwrap(); + print!("DEBUG: msg {}", msg); + { + let mut arc_w = arc_w.write().unwrap(); + arc_w.push(msg); + } // write lock is released at the end of this scope + } + }); + + for stream in listener.incoming() { + match stream { + Err(_) => println!("listen error"), + Ok(mut stream) => { + println!("connection from {} to {}", + stream.peer_addr().unwrap(), + stream.local_addr().unwrap()); + let send = send.clone(); + let arc = arc.clone(); + spawn(move|| { + let mut stream = BufStream::new(stream); + handle_connection(&mut stream, send, arc); + }); + } + } + } +}