diff --git a/chat-server/Cargo.lock b/chat-server/Cargo.lock new file mode 100644 index 0000000..4a93b9e --- /dev/null +++ b/chat-server/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "chat-server" +version = "0.1.0" diff --git a/chat-server/Cargo.toml b/chat-server/Cargo.toml new file mode 100644 index 0000000..b6d0cf9 --- /dev/null +++ b/chat-server/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "chat-server" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/chat-server/src/main.rs b/chat-server/src/main.rs new file mode 100644 index 0000000..da03127 --- /dev/null +++ b/chat-server/src/main.rs @@ -0,0 +1,65 @@ +use std::io::{Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::sync::{Arc, Mutex}; +use std::thread; + +fn handle_client( mut stream: TcpStream, clients: Arc>>) { + let client_stream = stream.try_clone().expect("Failed to clone stream."); + + { + println!("Client connected: {}", client_stream.peer_addr().unwrap()); + let mut clients = clients.lock().unwrap(); + clients.push(client_stream.try_clone().expect("Failed to clone stream.")); + } + + let mut buf = [0; 512]; + loop { + match stream.read(&mut buf) { + Ok(0) => { + // let mut clients = clients.lock().unwrap(); + // clients.retain(|c| *c != stream); + println!("Client disconnected: {}", stream.peer_addr().unwrap()); + return; + } + Ok(n) => { + let msg = String::from_utf8_lossy(&buf[..n]); + println!("Received message: {} from {}", msg, stream.peer_addr().unwrap()); + broadcast(&clients, msg); + } + Err(e) => { + eprintln!("Error reading from socket: {}", e); + return; + } + } + } +} + +fn broadcast(clients: &Arc>>, msg: std::borrow::Cow<'_, str>) { + + let clients = clients.lock().unwrap(); + + for mut client in clients.iter() { + let _ = client.write(msg.as_bytes()); + } +} + +fn main() { + let listener = TcpListener::bind("127.0.0.1:8080").expect("Failed to bind"); + println!("Server listening on port 8080..."); + + let clients: Arc>> = Arc::new(Mutex::new(Vec::new())); + + for stream in listener.incoming() { + match stream { + Ok(stream) => { + let clients = Arc::clone(&clients); + thread::spawn(move || { + handle_client(stream, clients); + }); + } + Err(e) => { + eprintln!("Error accepting connection: {}", e); + } + } + } +}