TCP Echo Server (Rust)
Topics: TcpListener, threads, cancellation, graceful shutdown
Problem
Implement a TCP server that echoes every byte it receives back to the sender.
pub struct Cancel(/* … */); // cooperative cancellation, stands in for Go's context
pub struct Server { /* … */ }
impl Server {
pub fn new(addr: &str, idle_timeout: Duration) -> Server;
pub fn start(&self, cancel: &Cancel) -> std::io::Result<()>;
pub fn addr(&self) -> String;
pub fn wait_started(&self, timeout: Duration) -> bool;
}
start binds the address, then serves until cancel is signalled; it returns Ok(()) on a
clean shutdown.
addr returns the actual bound address (e.g. 127.0.0.1:54321) once bound — useful when the
caller asked for port 0.
wait_started blocks until the listener is bound (or times out), so callers don't poll.
- Handle each connection in its own thread; enforce
idle_timeout with read/write timeouts; wait
for all handlers before returning.
Key concepts
- Non-blocking accept:
set_nonblocking(true) then poll, so the accept loop can observe the
cancellation token instead of blocking forever.
- Close then drain: drop the listener as soon as cancellation is seen (so new connects are
refused immediately), then
join the in-flight handlers.
- Read/write timeouts:
set_read_timeout/set_write_timeout give each accepted (blocking)
socket its idle deadline.
- Bound signal: publish the bound address through a
(Mutex, Condvar) pair so wait_started
blocks without polling.
Grading
Your solution.rs is compiled together with a trusted tests.rs (which include!s it) using
rustc --test. Only solution.rs is yours to edit.
Sign in to submit your solution.