Final Project: Building a Multithreaded Web Server
This chapter brings together everything you've learned so far to build a practical, real-world project: a web server.
Project Overview
We'll build a web server that:
- Listens for incoming TCP connections
- Parses HTTP requests
- Responds with HTML content
- Handles multiple requests concurrently using a thread pool
- Implements graceful shutdown
This project demonstrates several important concepts:
- TCP and HTTP networking - Understanding how web servers communicate
- Thread pools - Managing concurrent work efficiently
- Graceful shutdown - Properly cleaning up resources
- Error handling - Building robust systems
What You'll Learn
Throughout this chapter, you'll practice:
- Working with the standard library's networking APIs
- Designing concurrent systems with thread pools
- Using channels for thread communication
- Implementing clean shutdown patterns
- Building a real, working application
Project Structure
We'll build this incrementally:
- Single-threaded server - Start simple with a basic working server
- Multithreaded server - Add concurrency using a thread pool
- Graceful shutdown - Implement clean termination
Each step builds on the previous one, giving you a chance to understand each concept before moving forward.
Setting Up
Create a new binary project:
cargo new webserver
cd webserver
Your project structure should look like:
webserver/
├── Cargo.toml
└── src/
└── main.ox
We'll also create a library module for the thread pool:
// src/lib.ox
Ready? Let's start building!
Files Overview
ch21-00-final-project-a-web-server.md- Project overview and learning objectivesch21-01-single-threaded.md- Building a basic single-threaded web serverch21-02-multithreaded.md- Implementing a thread pool for concurrent request handlingch21-03-graceful-shutdown-and-cleanup.md- Adding graceful shutdown capabilities
Project Summary
This chapter guides you through building a web server that:
- Listens on a TCP socket for incoming connections
- Parses HTTP requests
- Handles multiple requests concurrently using a thread pool
- Gracefully shuts down when signaled
Key Oxide Features Demonstrated
- var keyword - Mutable variable declaration (replaces Rust's
let mut) - String interpolation - Using
\(variable)syntax - Path notation - Using
.instead of::(e.g.,std.io.Write) - extension keyword - Implementing methods on types
- Match expressions - Pattern matching on message types
- Closures - Using
{ params -> body }closures with thread spawning - Trait objects -
dyn Fn() + Send + 'static - Null types - Using
T?syntax - Result type - Error handling with
Result<T, E>
Code Examples
Main Topics
TCP and HTTP Networking
- Binding to a TCP socket with
TcpListener.bind() - Accepting connections with
listener.incoming() - Reading HTTP requests with
BufReader - Writing HTTP responses with
Writetrait
Thread Pool Implementation
- Using
mpscchannels for job distribution Arc<Mutex<T>>for thread-safe shared state- Worker threads spawned with
thread.spawn() - Message passing between threads
- Graceful shutdown with explicit terminate messages
Concurrency Patterns
- Fixed-size thread pools vs. unbounded thread spawning
- Queue-based job distribution
- Thread synchronization with mutexes and channels
- Clean shutdown coordination
Building the Project
# Create the project
cargo new webserver
cd webserver
# Build
cargo build
# Run
cargo run
# Test with curl
curl http://127.0.0.1:7878
Related Rust Book Chapter
This chapter is adapted from: The Rust Book Chapter 21: Final Project - Building a Multithreaded Web Server
Learning Outcomes
After completing this chapter, you will understand:
- How TCP connections and HTTP protocols work
- How to build concurrent systems with thread pools
- Thread-safe communication using channels
- Graceful shutdown patterns
- Real-world systems design in Oxide/Rust
- Performance considerations in concurrent programming
Important Oxide vs Rust Differences
| Rust | Oxide | Notes |
|---|---|---|
let mut x | var x | Mutable bindings use var |
format!() | String interpolation | Use "\(var)" syntax |
std::io | std.io | Path separators are . not :: |
| ` | x | x * 2` |
_ wildcard | _ wildcard | Pattern matching uses _ |
fn new() | static fn new() | Static methods use static keyword |
None | null | Nullability is built-in with T? |
Testing the Server
The single-threaded version demonstrates basic functionality.
The multithreaded version can be tested with concurrent requests:
# Terminal 1
cargo run
# Terminal 2
curl http://127.0.0.1:7878 &
curl http://127.0.0.1:7878 &
curl http://127.0.0.1:7878 &
wait
All requests should complete concurrently.
Extension Ideas
To further explore the concepts, consider:
- Adding logging with a logging crate
- Implementing more complex routing (pattern matching on paths)
- Adding middleware for request/response processing
- Implementing HTTPS with TLS
- Adding static file serving with caching
- Building a REST API handler
Notes
- This is a learning project demonstrating concurrency concepts
- For a production web server, use an established framework like Actix or Tokio
- The thread pool is intentionally simple to show the concepts clearly
- Real servers would handle errors more gracefully