Hi, i'm doing a TCP server in rust and i want to do a "feature".
the feature consists in: when i Ctrl + C, all the clients connected receives a "STOP" message.
but the compiler throw me an error:
--> src\main.rs:46:17
|
26 | let mut users = Vec::<User>::new();
| --------- move occurs because `users` has type `Vec<User>`, which does not implement the `Copy` trait
27 | let socket = TcpListener::bind("127.0.0.1:5050").unwrap();
28 | let users_in_arc = Arc::new(Mutex::new(users));
| ----- value moved here
...
46 | / users.push(User {
47 | | name,
48 | | socket: stream.try_clone().unwrap()
49 | | });
| |__________________^ value borrowed here after move
this is my code:
use ctrlc as signal;
use std::io::{Write, Read, Error};
use std::process::exit;
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use std::thread;
#[allow(unused)]
struct User {
name: String,
socket: Arc<Mutex<TcpStream>>,
}
fn handle_connection(_stream: &mut TcpStream) {}
fn request_data(connection: &mut TcpStream) -> Result<String, Error> {
connection.write_all(b"NICK").unwrap();
let mut name= String::new();
match connection.read_to_string(&mut name) {
Ok(_) => Ok(name),
Err(err) => Err(err)
}
}
fn main() {
let socket = TcpListener::bind("127.0.0.1:5050").unwrap();
let users_in_arc = Arc::new(Mutex::new(Vec::<User>::new()));
// Signal detection
signal::set_handler(move || {
println!("πͺ Exiting...");
let users_ref = users_in_arc.clone();
let mut users = users_ref.lock().unwrap();
users.iter_mut().for_each(|user| {
let mut socket = user.socket.lock().unwrap();
socket.write(b"STOP");
});
exit(1);
}).expect("β Error setting Signal Handler");
println!("π Listening on: {}", socket.local_addr().unwrap());
let users_in_arc_clone = users_in_arc.clone();
thread::spawn(move || {
// Accept connections in a loop
for stream in socket.incoming() {
if let Ok(mut stream) = stream {
println!("β³ Receiving connection... Awaiting Authentication.");
if let Ok(name) = request_data(&mut stream) {
println!("β
Client {} authorized.", &name);
// Get a mutable reference to the Arc<Mutex<TcpStream>>
let users_ref = &users_in_arc_clone;
let mut users = users_ref.lock().unwrap();
// Push the new user to the vector
users.push(User {
name,
socket: Arc::new(Mutex::new(stream.try_clone().unwrap()))
});
handle_connection(&mut stream);
} else {
println!("π‘ Connection canceled.");
}
}
}
});
// for stream in socket.incoming() {
// if let Ok(mut stream) = stream {
// println!("β³ Receiving connection... Awaiting Authentication.");
// if let Ok(name) = request_data(&mut stream) {
// println!("β
Client {} authorized.", &name);
// let users_ref = users_in_arc.clone();
// let mut users = users_ref.lock().unwrap();
// // Push the new user to the vector
// users.push(User {
// name,
// socket: Arc::new(Mutex::new(stream.try_clone().unwrap()))
// });
// handle_connection(&mut stream);
// } else {
// println!("π‘ Connection canceled.");
// }
// }
// }
}
how can i share the vector of users to push new connections and send "simultaneously" the "STOP" message?
chat gpt didn't help much :(