use tokio::io::{ErrorKind, Interest}; use tokio::net::{TcpListener, TcpStream}; pub(crate) struct TcpServer; impl TcpServer { pub(crate) async fn init() { match TcpListener::bind("127.0.0.1:12345").await { Ok(listener) => loop { match listener.accept().await { Ok((socket, addr)) => { log::info!("New client connected: {addr}"); tokio::spawn(async { Self::process(socket).await }); } Err(e) => log::error!("Couldn't get client: {e:?}"), } }, Err(e) => log::error!("Failed to bind port: {e:?}"), } } async fn process(socket: TcpStream) { loop { match socket.ready(Interest::READABLE | Interest::WRITABLE).await { Ok(ready) => { if ready.is_readable() { let mut buffer = Vec::with_capacity(1024); match socket.try_read_buf(&mut buffer) { // We need to write to client after reading from that, // so we use `continue` here instead if `break`. Ok(_) => { log::info!("Received contents"); // TODO: Start dispatching messages here. continue; } Err(e) if e.kind() == ErrorKind::WouldBlock => continue, Err(e) => { log::error!("Failed to read from TCP client socket: {e}"); break; } } } if ready.is_writable() { match socket.try_write(b"Hello from server written in Rust!") { Ok(_) => continue, Err(e) if e.kind() == ErrorKind::WouldBlock => continue, Err(e) => { log::error!("Failed to write to TCP client socket: {e}"); break; } } } } Err(e) => log::error!("Failed to wait for any states: {e}"), } } } }