(tools, client, server) feat: Complete ProtoBuf message transmission with both TCP and UDP
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
mod command_helper;
|
||||
mod message_dispatcher;
|
||||
mod protocol;
|
||||
mod server_logger;
|
||||
mod servers;
|
||||
mod services;
|
||||
|
||||
use server_logger::ServerLogger;
|
||||
use servers::tcp_server::TCP_SERVER;
|
||||
|
48
Server/src/message_dispatcher.rs
Normal file
48
Server/src/message_dispatcher.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use prost::Message;
|
||||
|
||||
use crate::protocol::{
|
||||
LoginRequest, LoginResponse, MessageType, RequestResult, SignupRequest, SignupResponse,
|
||||
};
|
||||
|
||||
pub(crate) fn dispatch_message(msg_type: u8, msg: &[u8]) -> Vec<u8> {
|
||||
let mut buf = Vec::new();
|
||||
|
||||
match msg_type {
|
||||
// Owing to Rust disallows converting an integer to an
|
||||
// enumeration (yet allows in reverse! ಠ_ಠ), we have to
|
||||
// use such this way to make this pattern matching works.
|
||||
//
|
||||
// This seems not as elegable as what we are expected,
|
||||
// but it could work well, provided that items in
|
||||
// `MessageType` doesn't excceed 256.
|
||||
val if val == MessageType::LoginRequest as u8 => {
|
||||
let msg = LoginRequest::decode(msg).unwrap();
|
||||
|
||||
log::info!("{msg:?}");
|
||||
|
||||
LoginResponse {
|
||||
result: RequestResult::Success.into(),
|
||||
message: "Successfully logged in!".into(),
|
||||
}
|
||||
.encode(&mut buf)
|
||||
.unwrap();
|
||||
|
||||
[vec![MessageType::LoginResponse as u8], buf].concat()
|
||||
}
|
||||
val if val == MessageType::SignupRequest as u8 => {
|
||||
let msg = SignupRequest::decode(msg).unwrap();
|
||||
|
||||
log::info!("{msg:?}");
|
||||
|
||||
SignupResponse {
|
||||
result: RequestResult::Success.into(),
|
||||
message: "Successfully signed up!".into(),
|
||||
}
|
||||
.encode(&mut buf)
|
||||
.unwrap();
|
||||
|
||||
[vec![MessageType::SignupResponse as u8], buf].concat()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
@ -2,3 +2,5 @@ pub(crate) mod tcp_server;
|
||||
pub(crate) mod udp_server;
|
||||
|
||||
const SERVER_ADDR: &str = "127.0.0.1:12345";
|
||||
const TCP_MAX_PAYLOAD_SIZE: usize = 1460;
|
||||
const UDP_MAX_PAYLOAD_SIZE: usize = 1472;
|
||||
|
@ -5,10 +5,12 @@ use std::sync::LazyLock;
|
||||
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::sync::{Mutex, mpsc};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::sync::mpsc::{self, Sender};
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
use super::SERVER_ADDR;
|
||||
use super::{SERVER_ADDR, TCP_MAX_PAYLOAD_SIZE};
|
||||
use crate::message_dispatcher;
|
||||
|
||||
pub(crate) static TCP_SERVER: LazyLock<Mutex<TcpServer>> =
|
||||
LazyLock::new(|| Mutex::new(TcpServer::new()));
|
||||
@ -16,7 +18,7 @@ pub(crate) static TCP_SERVER: LazyLock<Mutex<TcpServer>> =
|
||||
pub(crate) struct TcpServer {
|
||||
is_running: bool,
|
||||
clients: HashMap<SocketAddr, JoinHandle<()>>,
|
||||
shutdown_tx: Option<mpsc::Sender<()>>,
|
||||
shutdown_tx: Option<Sender<()>>,
|
||||
}
|
||||
|
||||
impl TcpServer {
|
||||
@ -31,13 +33,14 @@ impl TcpServer {
|
||||
pub(crate) async fn start(&mut self) {
|
||||
if self.is_running {
|
||||
log::warn!("TCP server is already running");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
match TcpListener::bind(SERVER_ADDR).await {
|
||||
Ok(listener) => {
|
||||
let (shutdown_tx, shutdown_rx) = mpsc::channel(1);
|
||||
self.is_running = true;
|
||||
let (shutdown_tx, shutdown_rx) = mpsc::channel(1);
|
||||
self.shutdown_tx = Some(shutdown_tx);
|
||||
|
||||
tokio::spawn(async move {
|
||||
@ -63,6 +66,7 @@ impl TcpServer {
|
||||
|
||||
for (addr, connection) in self.clients.drain() {
|
||||
log::info!("Closing connection to {}", addr);
|
||||
|
||||
connection.abort();
|
||||
}
|
||||
}
|
||||
@ -79,6 +83,7 @@ impl TcpServer {
|
||||
if let Err(e) = Self::handle_client(socket, addr).await {
|
||||
log::error!("Client {addr} error: {e}");
|
||||
}
|
||||
|
||||
log::info!("Client {addr} disconnected");
|
||||
});
|
||||
|
||||
@ -91,6 +96,7 @@ impl TcpServer {
|
||||
|
||||
_ = shutdown_rx.recv() => {
|
||||
log::info!("TCP Server shutting down");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -98,18 +104,18 @@ impl TcpServer {
|
||||
}
|
||||
|
||||
async fn handle_client(mut socket: TcpStream, addr: SocketAddr) -> io::Result<()> {
|
||||
let mut buffer = [0; 1024];
|
||||
|
||||
loop {
|
||||
let mut buffer = [0; TCP_MAX_PAYLOAD_SIZE];
|
||||
let len = socket.read(&mut buffer).await?;
|
||||
if len == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
log::debug!("Received {} bytes from {}", len, addr);
|
||||
log::info!("Received {} bytes from {}", len, addr);
|
||||
|
||||
// TODO: Deserialize data
|
||||
socket.write_all(&buffer[..len]).await?;
|
||||
let response = message_dispatcher::dispatch_message(buffer[0], &buffer[1..len]);
|
||||
|
||||
socket.write_all(&response).await?;
|
||||
}
|
||||
|
||||
let mut server = TCP_SERVER.lock().await;
|
||||
|
@ -4,7 +4,8 @@ use std::sync::LazyLock;
|
||||
use tokio::net::UdpSocket;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use super::SERVER_ADDR;
|
||||
use super::{SERVER_ADDR, UDP_MAX_PAYLOAD_SIZE};
|
||||
use crate::message_dispatcher;
|
||||
|
||||
pub(crate) static UDP_SERVER: LazyLock<Mutex<UdpServer>> =
|
||||
LazyLock::new(|| Mutex::new(UdpServer::new()));
|
||||
@ -21,6 +22,7 @@ impl UdpServer {
|
||||
pub(crate) async fn start(&mut self) {
|
||||
if self.is_running {
|
||||
log::warn!("UDP server is already running");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -50,17 +52,17 @@ impl UdpServer {
|
||||
|
||||
async fn handle_client(socket: &UdpSocket) -> io::Result<()> {
|
||||
loop {
|
||||
let mut buffer = [0; 1024];
|
||||
let mut buffer = [0; UDP_MAX_PAYLOAD_SIZE];
|
||||
let (len, addr) = socket.recv_from(&mut buffer).await?;
|
||||
if len == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
log::info!("Received message from client {addr}");
|
||||
log::info!("Received {} bytes from {}", len, addr);
|
||||
|
||||
// TODO: Deserialize data
|
||||
let buffer = &buffer[..len];
|
||||
socket.send_to(buffer, addr).await?;
|
||||
let response = message_dispatcher::dispatch_message(buffer[0], &buffer[1..len]);
|
||||
|
||||
socket.send_to(&response, addr).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1 +0,0 @@
|
||||
pub(crate) mod game_service;
|
@ -1 +0,0 @@
|
||||
|
Reference in New Issue
Block a user