A multi-threaded HTTP server built in Rust from scratch - implementing a custom Thread Pool with graceful shutdown. Handles concurrent connections without spawning unlimited threads.
┌─────────────────────────────┐
│ TCP Listener │
│ TcpListener::bind() │
│ 127.0.0.1:7878 │
└──────────────┬──────────────┘
│ incoming connections
▼
┌─────────────────────────────┐
│ main.rs │
│ for stream in listener { │
│ pool.execute(|| { │
│ handle_connection(s) │
│ }) │
│ } │
└──────────────┬──────────────┘
│ sends Job via channel
▼
┌──────────────────────────────────────────────────────────────────┐
│ ThreadPool │
│ │
│ execute(f) ──► sender.send(Message::NewJob(job)) │
│ │ │
│ mpsc::channel (Job Queue) │ │
│ ════════════════════════════╪════════ │
│ Arc<Mutex<Receiver>> │
│ (shared across all workers) │
│ │ │ │ │
│ ┌──────────▼─┐ ┌────▼───────┐ ┌▼───────────┐ │
│ │ Worker 0 │ │ Worker 1 │ │ Worker N │ │
│ │ │ │ │ │ │ │
│ │ lock() │ │ lock() │ │ lock() │ │
│ │ recv() │ │ recv() │ │ recv() │ │
│ │ job() ──► │ │ job() ──► │ │ job() ──► │ │
│ │ response │ │ response │ │ response │ │
│ └────────────┘ └────────────┘ └────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│
┌──────────────────▼───────────────────┐
│ Request Handling │
│ │
│ GET / ──► 200 + index.html │
│ GET /other ──► 404 + 404.html │
└──────────────────────────────────────┘
Drop(ThreadPool)
│
├─── Send Message::Terminate ──► Worker 0 breaks loop
├─── Send Message::Terminate ──► Worker 1 breaks loop
├─── Send Message::Terminate ──► Worker N breaks loop
│
└─── thread.join() for each worker ──► clean exit
ThreadPool::execute(job)
│
▼
sender.send(Message::NewJob(job))
│
│ mpsc channel
▼
receiver (Arc<Mutex<Receiver>>)
│
▼ first worker to acquire lock wins
Worker::recv() → match Message {
NewJob(job) => job(), // execute the closure
Terminate => break, // exit the loop
}
subodhkd001-multi_threaded_rust_server/
├── Cargo.toml # Package metadata
├── index.html # Served on GET /
├── 404.html # Served on any unknown route
└── src/
└── lib.rs # ThreadPool, Worker, Message — all concurrency logic
- Rust (edition 2024)
git clone https://github.com/subodhkd001/multi_threaded_rust_server.git
cd multi_threaded_rust_server
cargo runThen open your browser at:
http://127.0.0.1:7878 → 200 OK (index.html)
http://127.0.0.1:7878/other → 404 (404.html)
Thread Pool — A fixed set of pre-spawned worker threads that pick up jobs from a shared queue. Avoids the overhead of spawning a new thread per request.
mpsc channel — ThreadPool holds the sender; all workers share the receiver wrapped in Arc<Mutex<>>. Whichever worker acquires the lock first handles the next job.
Graceful Shutdown — On Drop, the pool sends a Terminate message for each worker, then joins all threads — ensuring in-flight requests complete before the process exits.
| Method | Description |
|---|---|
ThreadPool::new(size) |
Creates a pool with size worker threads. Panics if size is 0. |
pool.execute(f) |
Sends a closure as a job to the worker queue. |
enum Message {
NewJob(Job), // carry a boxed closure to a worker
Terminate, // signal a worker to shut down
}Each worker spawns a thread that loops — locking the receiver, receiving a message, and either running the job or breaking on Terminate.
📝 License
This project is open source and available under the MIT License.