├── README.md └── chat ├── client ├── Cargo.toml └── src │ └── main.rs └── server ├── Cargo.toml └── src └── main.rs /README.md: -------------------------------------------------------------------------------- 1 | # Rust_client-server_chat 2 | 3 | # A simple rust client/server chat program 4 | 5 | ## Run `cargo run` to run the app, run `cargo build` to build an executable file. 6 | 7 | ### Check out the Youtube Tutorial for this [Rust Tutorial](https://youtu.be/CIhlfJSvxe4). Here is our [Youtube Channel](https://www.youtube.com/channel/UCYqCZOwHbnPwyjawKfE21wg) Subscribe for more content. 8 | 9 | ### Check out our blog at [tensor-programming.com](http://tensor-programming.com/). 10 | 11 | ### Our [Twitter](https://twitter.com/TensorProgram), our [facebook](https://www.facebook.com/Tensor-Programming-1197847143611799/) and our [Steemit](https://steemit.com/@tensor). 12 | -------------------------------------------------------------------------------- /chat/client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "client" 3 | version = "0.1.0" 4 | authors = ["tensor-programming "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /chat/client/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, ErrorKind, Read, Write}; 2 | use std::net::TcpStream; 3 | use std::sync::mpsc::{self, TryRecvError}; 4 | use std::thread; 5 | use std::time::Duration; 6 | 7 | const LOCAL: &str = "127.0.0.1:6000"; 8 | const MSG_SIZE: usize = 32; 9 | 10 | fn main() { 11 | let mut client = TcpStream::connect(LOCAL).expect("Stream failed to connect"); 12 | client.set_nonblocking(true).expect("failed to initiate non-blocking"); 13 | 14 | let (tx, rx) = mpsc::channel::(); 15 | 16 | thread::spawn(move || loop { 17 | let mut buff = vec![0; MSG_SIZE]; 18 | match client.read_exact(&mut buff) { 19 | Ok(_) => { 20 | let msg = buff.into_iter().take_while(|&x| x != 0).collect::>(); 21 | println!("message recv {:?}", msg); 22 | }, 23 | Err(ref err) if err.kind() == ErrorKind::WouldBlock => (), 24 | Err(_) => { 25 | println!("connection with server was severed"); 26 | break; 27 | } 28 | } 29 | 30 | match rx.try_recv() { 31 | Ok(msg) => { 32 | let mut buff = msg.clone().into_bytes(); 33 | buff.resize(MSG_SIZE, 0); 34 | client.write_all(&buff).expect("writing to socket failed"); 35 | println!("message sent {:?}", msg); 36 | }, 37 | Err(TryRecvError::Empty) => (), 38 | Err(TryRecvError::Disconnected) => break 39 | } 40 | 41 | thread::sleep(Duration::from_millis(100)); 42 | }); 43 | 44 | println!("Write a Message:"); 45 | loop { 46 | let mut buff = String::new(); 47 | io::stdin().read_line(&mut buff).expect("reading from stdin failed"); 48 | let msg = buff.trim().to_string(); 49 | if msg == ":quit" || tx.send(msg).is_err() {break} 50 | } 51 | println!("bye bye!"); 52 | 53 | } 54 | -------------------------------------------------------------------------------- /chat/server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "server" 3 | version = "0.1.0" 4 | authors = ["tensor-programming "] 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /chat/server/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::{ErrorKind, Read, Write}; 2 | use std::net::TcpListener; 3 | use std::sync::mpsc; 4 | use std::thread; 5 | 6 | const LOCAL: &str = "127.0.0.1:6000"; 7 | const MSG_SIZE: usize = 32; 8 | 9 | fn sleep() { 10 | thread::sleep(::std::time::Duration::from_millis(100)); 11 | } 12 | 13 | fn main() { 14 | let server = TcpListener::bind(LOCAL).expect("Listener failed to bind"); 15 | server.set_nonblocking(true).expect("failed to initialize non-blocking"); 16 | 17 | let mut clients = vec![]; 18 | let (tx, rx) = mpsc::channel::(); 19 | loop { 20 | if let Ok((mut socket, addr)) = server.accept() { 21 | println!("Client {} connected", addr); 22 | 23 | let tx = tx.clone(); 24 | clients.push(socket.try_clone().expect("failed to clone client")); 25 | 26 | thread::spawn(move || loop { 27 | let mut buff = vec![0; MSG_SIZE]; 28 | 29 | match socket.read_exact(&mut buff) { 30 | Ok(_) => { 31 | let msg = buff.into_iter().take_while(|&x| x != 0).collect::>(); 32 | let msg = String::from_utf8(msg).expect("Invalid utf8 message"); 33 | 34 | println!("{}: {:?}", addr, msg); 35 | tx.send(msg).expect("failed to send msg to rx"); 36 | }, 37 | Err(ref err) if err.kind() == ErrorKind::WouldBlock => (), 38 | Err(_) => { 39 | println!("closing connection with: {}", addr); 40 | break; 41 | } 42 | } 43 | 44 | sleep(); 45 | }); 46 | } 47 | 48 | if let Ok(msg) = rx.try_recv() { 49 | clients = clients.into_iter().filter_map(|mut client| { 50 | let mut buff = msg.clone().into_bytes(); 51 | buff.resize(MSG_SIZE, 0); 52 | 53 | client.write_all(&buff).map(|_| client).ok() 54 | }).collect::>(); 55 | } 56 | 57 | sleep(); 58 | } 59 | } 60 | --------------------------------------------------------------------------------