ping pong works (with a python client)
cargo devel CI / cargo CI (push) Successful in 2m8s Details

This commit is contained in:
Christoph J. Scherr 2024-01-19 16:33:11 +01:00
parent a9bf861a0b
commit 6868af2016
Signed by: cscherrNT
GPG Key ID: 8E2B45BC51A27EA7
3 changed files with 49 additions and 18 deletions

21
scripts/client.py Normal file
View File

@ -0,0 +1,21 @@
import socket
HOST = "127.0.0.1"
PORT = 9999
payload = b"ping\0"
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
try:
s.sendall(payload)
print("> ping")
except Exception as e:
break
reply = s.recv(1024).decode()
if reply == "":
break
print(f"< {reply}")
print("connection shut down")

View File

@ -3,6 +3,8 @@ use clap::ValueEnum;
use std::{fmt::Display, time::Duration}; use std::{fmt::Display, time::Duration};
const DEFAULT_TIMEOUT_LEN: u64 = 5000; // ms const DEFAULT_TIMEOUT_LEN: u64 = 5000; // ms
const DEFAULT_DELAY_LEN: u64 = 500; // ms
const DEFAULT_WIN_AFTER: usize = 20;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Mode { pub enum Mode {
@ -45,6 +47,8 @@ pub struct Config {
pub mode: Mode, pub mode: Mode,
pub threads: usize, pub threads: usize,
pub timeout: Duration, pub timeout: Duration,
pub delay: Duration,
pub win_after: usize,
} }
impl Config { impl Config {
@ -54,6 +58,8 @@ impl Config {
mode: cli.mode.clone(), mode: cli.mode.clone(),
threads: cli.threads, threads: cli.threads,
timeout: Duration::from_millis(DEFAULT_TIMEOUT_LEN), timeout: Duration::from_millis(DEFAULT_TIMEOUT_LEN),
delay: Duration::from_millis(DEFAULT_DELAY_LEN),
win_after: DEFAULT_WIN_AFTER,
} }
} }
} }

View File

@ -1,14 +1,9 @@
#![cfg(feature = "server")] #![cfg(feature = "server")]
use std::{error::Error, net::SocketAddr, time::Duration}; use std::time::Duration;
use anyhow::anyhow; use libpt::log::{debug, info, trace, warn};
use libpt::{
bintols::display::humanbytes,
log::{debug, error, info, trace, warn},
};
use threadpool::ThreadPool;
use tokio::{ use tokio::{
io::{AsyncReadExt, BufReader, AsyncBufReadExt}, io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
net::{TcpListener, TcpStream}, net::{TcpListener, TcpStream},
time::timeout, time::timeout,
}; };
@ -20,7 +15,6 @@ use errors::*;
pub struct Server { pub struct Server {
cfg: Config, cfg: Config,
pool: ThreadPool,
pub timeout: Option<Duration>, pub timeout: Option<Duration>,
server: TcpListener, server: TcpListener,
} }
@ -28,11 +22,9 @@ pub struct Server {
impl Server { impl Server {
pub async fn build(cfg: Config) -> anyhow::Result<Self> { pub async fn build(cfg: Config) -> anyhow::Result<Self> {
let server = TcpListener::bind(cfg.addr).await?; let server = TcpListener::bind(cfg.addr).await?;
let pool = ThreadPool::new(cfg.threads);
let timeout = Some(Duration::from_secs(5)); let timeout = Some(Duration::from_secs(5));
Ok(Server { Ok(Server {
cfg, cfg,
pool,
timeout, timeout,
server, server,
}) })
@ -64,6 +56,7 @@ impl Server {
} }
async fn handle_stream(&self, stream: TcpStream) -> Result<()> { async fn handle_stream(&self, stream: TcpStream) -> Result<()> {
let mut pings: usize = 0;
let addr = match stream.peer_addr() { let addr = match stream.peer_addr() {
Ok(a) => a, Ok(a) => a,
Err(err) => { Err(err) => {
@ -93,13 +86,24 @@ impl Server {
trace!("len is apperently 0: {len:?}"); trace!("len is apperently 0: {len:?}");
break; break;
} else { } else {
info!( let msg = self.decode(&buf)?;
"< {:?}\t({})\n{}", info!("< {:?} : {}", addr, msg);
addr, if msg.contains("ping") {
humanbytes(len), pings += 1;
self.decode(&buf)? }
); if pings < self.cfg.win_after {
reader.write_all(b"pong\0").await?;
info!("> {:?} : pong", addr,);
} else {
reader.write_all(b"you win!\0").await?;
info!("> {:?} : you win!", addr,);
reader.shutdown().await?;
break;
}
buf.clear(); buf.clear();
// we should wait, so that we don't spam the client
std::thread::sleep(self.cfg.delay);
} }
} }
info!("disconnected peer: {:?}", addr); info!("disconnected peer: {:?}", addr);
@ -108,7 +112,7 @@ impl Server {
#[inline] #[inline]
fn decode(&self, buf: &Vec<u8>) -> Result<String> { fn decode(&self, buf: &Vec<u8>) -> Result<String> {
Ok(String::from_utf8(buf.clone())?) Ok(String::from_utf8(buf.clone())?.replace('\n', "\\n"))
} }
#[inline] #[inline]