use std::os::fd::AsRawFd; use tokio::net::*; use tokio::runtime::*; type Fd = TcpStream; mod http; use http::*; async fn server_conn(conn: Fd, size: usize) { let _ = conn.set_linger(Some(Duration::default())); loop { let mut req = HttpReq::new(); if let Err(_) = req.read(&conn).await { break; } let rsp = HttpRsp::new(size); if let Err(_) = rsp.write(&conn).await { break; } } unsafe { libc::shutdown(conn.as_raw_fd(), libc::SHUT_RDWR) }; } async fn server(port: u16, size: usize) { let addr = format!("127.0.0.1:{}", port); let server = match TcpListener::bind(addr).await { Ok(server) => server, Err(e) => { println!("tcp_server fail: {e:?}"); return; } }; loop { match server.accept().await { Ok((conn, _)) => { let _ = tokio::spawn(server_conn(conn, size)); } Err(_e) => {} }; } } use std::time::*; fn help() { println!("{} options", hictor::program_invocation_name()); println!("options:"); println!("--addr | -a: listening addr, format is port | ip:port"); println!("--threads | -t: default is the number of cores available to the system"); println!("--size | -s: body_length"); println!("--help | -h: print help message"); } fn main() { let opts = hiopt::options!["addr:", "a:", "size:", "s:", "threads:", "t:", "help", "h"]; let args = unsafe { hiopt::raw_args_from_i8(hictor::args()) }; let mut port = 2001_u16; let mut size = 1024_usize; let mut nth = 0_usize; for opt in opts.opt_iter(&args[1..]) { let (optidx, optval) = opt.unwrap(); match optidx { 0..=1 => port = optval.unwrap().parse().unwrap(), 2..=3 => size = optval.unwrap().parse().unwrap(), 4..=5 => nth = optval.unwrap().parse().unwrap(), 6..=7 => return help(), _ => unreachable!(), } } let rt = if nth == 0 { Builder::new_multi_thread().enable_all().build().unwrap() } else { Builder::new_multi_thread() .enable_all() .worker_threads(nth) .build() .unwrap() }; let _ = rt.block_on(server(port, size)); }