New Rustacean advice on Rust TCP Server

Hey, Trying to get a better feel for rust and was able to get a TCP server working! Would like feedback on if this is a good way to do this or if anything can / should be changed. Thanks in advance!

Server itself:

use std::io::Read;
use std::net::TcpListener;
use std::sync::{Arc, Mutex};
use std::thread;

pub struct Message {
    pub origin: String,
    pub data: String,
}


pub trait NetworkListener {
    fn port(&self) -> u16;
    fn on_online(&self);
    fn on_message(&mut self, message: Message) -> ();
}

pub fn run_server<T: NetworkListener + Sync + Send + 'static>(state_ref: Arc<Mutex<T>>) {
    let online_callback = state_ref.clone();

    let state = online_callback.lock().unwrap();
    let listener = TcpListener::bind(format!("127.0.0.1:{}", state.port())).unwrap();
    state.on_online();
    drop(state);
    drop(online_callback);

    loop {
        for stream in listener.incoming() {
            match stream {
                Ok(mut stream) => {
                    let state_ref_2 = state_ref.clone();

                    thread::spawn(move || {
                        // Read the message
                        let mut buffer = [0; 1024];
                        let read = stream.read(&mut buffer).unwrap();

                        // Write to results

                        let message: Message = Message {
                            origin: stream.peer_addr().unwrap().to_string(),
                            data: String::from_utf8_lossy(&buffer[..read]).to_string(),
                        };
                    
                        state_ref_2.lock().unwrap().on_message(message);
                    });
                }
                Err(e) => {
                    println!("Connection failed: {}", e);
                }
            }
        }
    }
}

Then you can use the server like so:


struct NetworkState {
    // Maybe add some state data here
}

impl NetworkListener for NetworkState {

    fn port(&self) -> u16 {
        9000
    }

    fn on_online(&self) {
        let log_str = format!("Network online on port {}", self.port());
        // Do Setup of something
    }

    fn on_message(&mut self, packet: Message) -> () {
        // Do something
    }
}

pub fn run() {
    thread::spawn(|| {
        let state = NetworkState {};
        run_server(Arc::new(Mutex::new(state)));
    });
}

I have a feeling this has some issues in terms of best practices.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.