From 60bedb7ff6a1313821517ae12cb30fb8714959ab Mon Sep 17 00:00:00 2001 From: Phuntsok Drak-pa Date: Wed, 21 Mar 2018 20:38:20 +0100 Subject: [PATCH] Further improvements for the server and client --- Lucien/Rust/Cargo.toml | 2 + Lucien/Rust/src/client.rs | 104 +++++++++++++++++++++++++++----------- Lucien/Rust/src/server.rs | 90 +++++++++++++++++++-------------- 3 files changed, 127 insertions(+), 69 deletions(-) diff --git a/Lucien/Rust/Cargo.toml b/Lucien/Rust/Cargo.toml index 6171117..cf2ba81 100644 --- a/Lucien/Rust/Cargo.toml +++ b/Lucien/Rust/Cargo.toml @@ -4,3 +4,5 @@ version = "0.2.0" authors = ["Lucien Cartier-Tilet "] [dependencies] +colored = "1.6" +chrono = "0.4" diff --git a/Lucien/Rust/src/client.rs b/Lucien/Rust/src/client.rs index ac866d2..647a51a 100644 --- a/Lucien/Rust/src/client.rs +++ b/Lucien/Rust/src/client.rs @@ -1,7 +1,11 @@ +extern crate chrono; +extern crate colored; use std; use std::io::*; use std::net::TcpStream; use std::thread; +use self::colored::*; +use self::chrono::Local; // static leave_msg: &str = "BYE"; @@ -12,12 +16,11 @@ fn get_entry() -> String { buf.replace("\n", "").replace("\r", "") } -fn write_to_server(stream: TcpStream) { - let mut writer = BufWriter::new(&stream); - - // entrée du nom d'utilisateur +fn get_name(writer: &mut BufWriter<&TcpStream>) { loop { - match &*get_entry() { + let mut line = &*get_entry(); + line = line.trim(); + match line { "" => { continue; } @@ -25,11 +28,10 @@ fn write_to_server(stream: TcpStream) { println!("Disconnecting..."); writeln!(writer, "BYE").unwrap(); writer.flush().unwrap(); - println!("Disconnected!"); return (); } line => { - let line_str : String = String::from(line); + let line_str: String = String::from(line); // let spliced: Vec<&str> = line_str.split(" ").collect(); let spliced: Vec<&str> = line_str.split_whitespace().collect(); if spliced.len() > 1 { @@ -40,19 +42,24 @@ fn write_to_server(stream: TcpStream) { writer.flush().unwrap(); } } - break; + return; } +} + +fn write_to_server(stream: TcpStream) { + let mut writer = BufWriter::new(&stream); + + // entrée du nom d'utilisateur + get_name(&mut writer); loop { - match &*get_entry() { - "" => { - ; - } + let line = &*get_entry(); + line.trim(); + match line { + "" => {} "/quit" => { - println!("Disconnecting..."); writeln!(writer, "BYE").unwrap(); writer.flush().unwrap(); - println!("Disconnected!"); return (); } "/clients" => { @@ -74,17 +81,18 @@ fn exchange_with_server(stream: TcpStream) { let stream_cpy = stream.try_clone().unwrap(); let mut reader = BufReader::new(&stream_cpy); - println!("Enter `/quit` when you want to leave"); - macro_rules! receive { () => ({ let mut line = String::new(); match reader.read_line(&mut line) { Ok(len) => { if len == 0 { - // Reader is at EOF. Could use ErrorKind::UnexpectedEOF, but still unstable. - let ret = std::io::Error::new(std::io::ErrorKind::Other, "test"); - return Err(ret): std::result::Result<&str, std::io::Error>; + // Reader is at EOF. Could use ErrorKind::UnexpectedEOF, + // but still unstable. + let ret = std::io::Error::new( + std::io::ErrorKind::Other, "test"); + return + Err(ret): std::result::Result<&str,std::io::Error>; } line.pop(); } @@ -101,13 +109,50 @@ fn exchange_with_server(stream: TcpStream) { match (|| loop { let input: String = String::from(receive!()); let spliced_input: Vec<&str> = input.split(" ").collect(); - // if spliced_input[0] == "FROM" { - // println!("<{}>: {}", spliced_input[1], spliced_input[3]); - // continue; - // } match spliced_input[0] { + "WELCOME" => { + println!("{}", "Successfully connected to the server.".green()); + println!("Type /clients to get the list of users connected"); + println!("Type /quit to disconnect and quit"); + } "FROM" => { - println!("<{}>: {}", spliced_input[1], spliced_input[3]); + let date = Local::now(); + let mut msg = String::new(); + for i in 3..spliced_input.len() { + msg.push_str(" "); + msg.push_str(spliced_input[i]); + } + println!( + "{} <{}>:{}", + date.format("%H:%M:%S").to_string().blue(), + spliced_input[1].red(), + msg + ); + } + "BYE" => { + return Ok("Ok"); + } + "LIST" => { + println!("{}", ">>>> LIST OF CLIENTS CONNECTED <<<<".bold().yellow()); + for i in 2..spliced_input.len() { + println!("\t\t{}", spliced_input[i]); + } + } + "JOIN" => { + println!( + "{}{}{}", + "-------> ".green(), + spliced_input[1], + " has joined".green() + ); + } + "LOGOUT" => { + println!( + "{}{}{}", + "<------- ".red(), + spliced_input[1], + " has left".red() + ); } _ => { println!("{}", input); @@ -117,23 +162,22 @@ fn exchange_with_server(stream: TcpStream) { })() { Ok(_) => { - println!("Left?"); + println!("{}", ">>> Successfully left the room <<<".green()); } - Err(_) => { - println!(">>> Successfully left the room <<<"); + Err(e) => { + println!("{}: {}", "Error: Function terminated too early".red(), e); } } } pub fn client(server_address: String) { - println!("Tentative de connexion a serveur..."); + println!("Trying to connect to the server..."); match TcpStream::connect(server_address) { Ok(stream) => { - println!("Connexion au serveur réussie !"); exchange_with_server(stream); } Err(e) => { - println!("La connection au serveur a échoué : {}", e); + println!("{} {}", "Connection to server failed:".red(), e); return; } } diff --git a/Lucien/Rust/src/server.rs b/Lucien/Rust/src/server.rs index 8053f2e..e46a8f9 100644 --- a/Lucien/Rust/src/server.rs +++ b/Lucien/Rust/src/server.rs @@ -17,7 +17,7 @@ use std::collections::HashMap; 1.5 [ ] 1.6 [ ] 1.7 [X] -1.8 [ ] +1.8 [X] 1.9 [ ] 2.1 [X] 2.2 [X] @@ -26,19 +26,28 @@ use std::collections::HashMap; 4.1.1 [X] 4.1.2 [X] 4.2.1 [X] -4.2.2 [X] +4.2.2 [-] */ /////////////////////////////////////////////////////////////////////////////// -// code // +// TYPES // /////////////////////////////////////////////////////////////////////////////// // Map for all connected clients containing their name and stream type UserMapValue = (String, TcpStream); type UserMap = HashMap; -fn distribute_message(msg: &str, not_to: &SocketAddr, lock: &mut MutexGuard) { +/////////////////////////////////////////////////////////////////////////////// +// CODE // +/////////////////////////////////////////////////////////////////////////////// + +fn distribute_message( + msg: &str, + not_to: &SocketAddr, + lock: &mut MutexGuard, + everyone: bool, +) { let mut name = String::new(); for (client, entry) in (*lock).iter() { if client == not_to { @@ -47,29 +56,30 @@ fn distribute_message(msg: &str, not_to: &SocketAddr, lock: &mut MutexGuard Result<()> { - let mut writer = BufWriter::new(other_stream); - // test if message begins with "MSG " ///////////////////////// - if &msg[..4] == "MSG " { - try!(writeln!(writer, "FROM {} {}", name, msg)); - } else { - try!(writeln!(writer, "{}", msg)); - } - /////////////////////////////////////////////////////////////// - try!(writer.flush()); - return Ok(()); - })() - { - Ok(_) => {} - Err(e) => { - println!( - "Client {} <{}> disappeared during message distribution: {}", - other_client, other_name, e - ); - } + let other_name = &entry.0; + let other_stream = &entry.1; + if everyone == false && other_client == not_to { + continue; + } + match (|| -> Result<()> { + let mut writer = BufWriter::new(other_stream); + // test if message begins with "MSG " ///////////////////////// + if &msg[..4] == "MSG " { + try!(writeln!(writer, "FROM {} {}", name, msg)); + } else { + try!(writeln!(writer, "{}", msg)); + } + /////////////////////////////////////////////////////////////// + try!(writer.flush()); + return Ok(()); + })() + { + Ok(_) => {} + Err(e) => { + println!( + "Client {} <{}> disappeared during message distribution: {}", + other_client, other_name, e + ); } } } @@ -78,16 +88,21 @@ fn distribute_message(msg: &str, not_to: &SocketAddr, lock: &mut MutexGuard) { let mut clients = String::new(); for (client, entry) in (*lock).iter() { - if client != to { - clients.push_str(&format!("{} ", &entry.0)); - } + &entry.0.trim_left(); + &entry.0.trim_right(); + clients.push_str(&format!( + "{}{} ", + if client == to { "(You)" } else { "" }, + &entry.0 + )); } + clients.trim_left(); println!("{}", clients); for (client, entry) in (*lock).iter() { if client == to { let stream = &entry.1; let mut writer = BufWriter::new(stream); - writeln!(writer, "{}", clients).unwrap(); + writeln!(writer, "LIST CLIENTS {}", clients).unwrap(); writer.flush().unwrap(); return; } @@ -96,7 +111,7 @@ fn send_clients_name(to: &SocketAddr, lock: &mut MutexGuard) { fn disconnect_user(name: &str, client: &SocketAddr, lock: &mut MutexGuard) { (*lock).remove(&client); - distribute_message(&format!("LOGOUT {}", name), client, lock); + distribute_message(&format!("LOGOUT {}", name), client, lock, true); } fn handle_client(stream: TcpStream, clients: Arc>) { @@ -144,7 +159,6 @@ fn handle_client(stream: TcpStream, clients: Arc>) { send!("Please enter your name:"); let name = receive!(); println!("Client {} identified as {}", client, name); - send!("DEBUG: You can now type messages. Leave this chat with the request `BYE`."); Ok(name) })() { @@ -159,7 +173,7 @@ fn handle_client(stream: TcpStream, clients: Arc>) { { let mut lock = clients.lock().unwrap(); (*lock).insert(client, (name.clone(), stream.try_clone().unwrap())); - distribute_message(&format!("JOIN {}", name), &client, &mut lock); + distribute_message(&format!("JOIN {}", name), &client, &mut lock, false); } writeln!(writer, "WELCOME").unwrap(); @@ -176,16 +190,14 @@ fn handle_client(stream: TcpStream, clients: Arc>) { send!("PONG"); } "REQ CLIENTS" => { - { - let mut lock = clients.lock().unwrap(); - send_clients_name(&client, &mut lock); - } + let mut lock = clients.lock().unwrap(); + send_clients_name(&client, &mut lock); } input => { println!("{} <{}>: {}", client, name, input); { let mut lock = clients.lock().unwrap(); - distribute_message(&format!("{}", input), &client, &mut lock); + distribute_message(&format!("{}", input), &client, &mut lock, true); } } }