Add per-connection state and async handlers
This commit is contained in:
+74
-11
@@ -1,40 +1,103 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
|
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
|
||||||
|
static NEXT_CONNECTION_ID: AtomicU64 = AtomicU64::new(1);
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> io::Result<()> {
|
async fn main() -> io::Result<()> {
|
||||||
let listener = TcpListener::bind("192.168.1.152:32768").await?;
|
let listener = TcpListener::bind("192.168.1.152:32768").await?;
|
||||||
|
|
||||||
println!("Сервер слушает 127.0.0.1:32768");
|
println!("Сервер слушает 192.168.1.152:32768");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (stream, client_addr) = listener.accept().await?;
|
let (stream, client_addr) = listener.accept().await?;
|
||||||
|
|
||||||
println!("Подключился клиент: {}", client_addr);
|
let connection_id =
|
||||||
|
NEXT_CONNECTION_ID.fetch_add(1, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let connection = Connection::new(
|
||||||
|
connection_id,
|
||||||
|
client_addr,
|
||||||
|
stream,
|
||||||
|
);
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(error) = handle_client(stream).await {
|
if let Err(error) = connection.run().await {
|
||||||
eprintln!("Ошибка клиента {client_addr}: {error}");
|
eprintln!(
|
||||||
|
"Обработчик {connection_id}: ошибка: {error}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
println!("Клиент {client_addr} отключился");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_client(mut stream:TcpStream) -> io::Result<()> {
|
struct Connection {
|
||||||
let mut buffer = [0_u8; 3];
|
id: u64,
|
||||||
|
client_addr: SocketAddr,
|
||||||
|
stream: TcpStream,
|
||||||
|
message_count: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Connection {
|
||||||
|
fn new(
|
||||||
|
id: u64,
|
||||||
|
client_addr: SocketAddr,
|
||||||
|
stream: TcpStream,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
client_addr,
|
||||||
|
stream,
|
||||||
|
message_count: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run(mut self) -> io::Result<()> {
|
||||||
|
println!(
|
||||||
|
"Обработчик {} создан для {}",
|
||||||
|
self.id,
|
||||||
|
self.client_addr
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut buffer = [0_u8; 1024];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let bytes_read = stream.read(&mut buffer).await?;
|
let bytes_read = self.stream.read(&mut buffer).await?;
|
||||||
|
|
||||||
if bytes_read == 0 {
|
if bytes_read == 0 {
|
||||||
|
println!(
|
||||||
|
"Обработчик {}: клиент {} отключился",
|
||||||
|
self.id,
|
||||||
|
self.client_addr
|
||||||
|
);
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("получено {bytes_read} байт {:?}", String::from_utf8_lossy(&buffer[..bytes_read]));
|
self.message_count += 1;
|
||||||
|
|
||||||
stream.write_all(&buffer[..bytes_read]).await?;
|
let received =
|
||||||
|
String::from_utf8_lossy(&buffer[..bytes_read]);
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Обработчик {}: сообщение №{}: {:?}",
|
||||||
|
self.id,
|
||||||
|
self.message_count,
|
||||||
|
received
|
||||||
|
);
|
||||||
|
|
||||||
|
let response = format!(
|
||||||
|
"Обработчик {}: сообщение №{}: {}\n",
|
||||||
|
self.id,
|
||||||
|
self.message_count,
|
||||||
|
received
|
||||||
|
);
|
||||||
|
|
||||||
|
self.stream.write_all(response.as_bytes()).await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user