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:

  1. Single-threaded server - Start simple with a basic working server
  2. Multithreaded server - Add concurrency using a thread pool
  3. 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 objectives
  • ch21-01-single-threaded.md - Building a basic single-threaded web server
  • ch21-02-multithreaded.md - Implementing a thread pool for concurrent request handling
  • ch21-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 Write trait

Thread Pool Implementation

  • Using mpsc channels 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

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

RustOxideNotes
let mut xvar xMutable bindings use var
format!()String interpolationUse "\(var)" syntax
std::iostd.ioPath separators are . not ::
`xx * 2`
_ wildcard_ wildcardPattern matching uses _
fn new()static fn new()Static methods use static keyword
NonenullNullability 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