Chat server: Difference between revisions
Content added Content deleted
(Add Rust implementation) |
|||
Line 2,967: | Line 2,967: | ||
#Turn on informational messages |
#Turn on informational messages |
||
ChatServer.new(7000, '0.0.0.0', 100, $stderr, true).start.join |
ChatServer.new(7000, '0.0.0.0', 100, $stderr, true).start.join |
||
</lang> |
|||
=={{header|Rust}}== |
|||
<lang rust> |
|||
use std::collections::HashMap; |
|||
use std::io; |
|||
use std::io::prelude::*; |
|||
use std::io::BufReader; |
|||
use std::net::{TcpListener, TcpStream}; |
|||
use std::sync::{Arc, RwLock}; |
|||
use std::thread; |
|||
type Username = String; |
|||
/// Sends a message to all clients except the sending client. |
|||
fn broadcast_message( |
|||
user: &str, |
|||
clients: &mut HashMap<String, TcpStream>, |
|||
message: &str, |
|||
) -> io::Result<()> { |
|||
for (client, stream) in clients.iter_mut() { |
|||
if client != user { |
|||
writeln!(stream, "{}", message)?; |
|||
} |
|||
} |
|||
Ok(()) |
|||
} |
|||
fn chat_loop(listener: &TcpListener) -> io::Result<()> { |
|||
let local_clients: Arc<RwLock<HashMap<Username, TcpStream>>> = |
|||
Arc::new(RwLock::new(HashMap::new())); |
|||
println!("Accepting connections on {}", listener.local_addr()?.port()); |
|||
for stream in listener.incoming() { |
|||
match stream { |
|||
Ok(stream) => { |
|||
let client_clients = Arc::clone(&local_clients); |
|||
thread::spawn(move || -> io::Result<()> { |
|||
let mut reader = BufReader::new(stream.try_clone()?); |
|||
let mut writer = stream; |
|||
let mut name = String::new(); |
|||
loop { |
|||
write!(writer, "Please enter a username: ")?; |
|||
reader.read_line(&mut name)?; |
|||
name = name.trim().to_owned(); |
|||
let clients = client_clients.read().unwrap(); |
|||
if !clients.contains_key(&name) { |
|||
writeln!(writer, "Welcome, {}!", &name)?; |
|||
break; |
|||
} |
|||
writeln!(writer, "That username is taken.")?; |
|||
name.clear(); |
|||
} |
|||
{ |
|||
let mut clients = client_clients.write().unwrap(); |
|||
clients.insert(name.clone(), writer); |
|||
broadcast_message( |
|||
&name, |
|||
&mut *clients, |
|||
&format!("{} has joined the chat room.", &name), |
|||
)?; |
|||
} |
|||
for line in reader.lines() { |
|||
let mut clients = client_clients.write().unwrap(); |
|||
broadcast_message(&name, &mut *clients, &format!("{}: {}", &name, line?))?; |
|||
} |
|||
{ |
|||
let mut clients = client_clients.write().unwrap(); |
|||
clients.remove(&name); |
|||
broadcast_message( |
|||
&name, |
|||
&mut *clients, |
|||
&format!("{} has left the chat room.", &name), |
|||
)?; |
|||
} |
|||
Ok(()) |
|||
}); |
|||
} |
|||
Err(e) => { |
|||
println!("Connection failed: {}", e); |
|||
} |
|||
} |
|||
} |
|||
Ok(()) |
|||
} |
|||
fn main() { |
|||
let listener = TcpListener::bind(("localhost", 7000)).unwrap(); |
|||
chat_loop(&listener).unwrap(); |
|||
} |
|||
</lang> |
</lang> |
||