How to Build a Multithreaded Web Server in Rust Without External Crates
How to Build a Multithreaded Web Server in Rust Without External Crates Rust’s powerful concurrency model and ownership system make it an excellent choice for building fast, safe web servers. In this article, you’ll learn how to implement a multithreaded web server from scratch using only the Rust standard library. 1. Project Setup Start with a new Rust project: cargo new rust_web_server cd rust_web_server 2. Reading and Responding to HTTP Requests Edit src/main.rs to include basic TCP listening and response logic: use std::io::prelude::*; use std::net::{TcpListener, TcpStream}; use std::thread; use std::fs; fn handle_connection(mut stream: TcpStream) { let mut buffer = [0; 1024]; stream.read(&mut buffer).unwrap(); let contents = fs::read_to_string("hello.html").unwrap(); let response = format!( "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}", contents.len(), contents ); stream.write(response.as_bytes()).unwrap(); stream.flush().unwrap(); } 3. Adding a Thread Pool To handle requests concurrently, we'll build a basic thread pool without any external dependencies: use std::sync::{mpsc, Arc, Mutex}; struct ThreadPool { workers: Vec, sender: mpsc::Sender, } type Job = Box Worker { let thread = thread::spawn(move || loop { let job = receiver.lock().unwrap().recv().unwrap(); println!("Worker {} got a job; executing.", id); job(); }); Worker { id, thread: Some(thread), } } } 4. Wiring It All Together fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); let pool = ThreadPool::new(4); for stream in listener.incoming().take(10) { let stream = stream.unwrap(); pool.execute(|| { handle_connection(stream); }); } println!("Shutting down server."); } 5. Testing Create a file named hello.html in your project root: Rust Web Server Hello from Rust! Conclusion This is a barebones but fully functioning multithreaded web server written entirely with the Rust standard library. From here, you can explore features like routing, middleware, and async IO using more advanced tools like tokio or hyper. If this post helped you, consider supporting me: buymeacoffee.com/hexshift
How to Build a Multithreaded Web Server in Rust Without External Crates
Rust’s powerful concurrency model and ownership system make it an excellent choice for building fast, safe web servers. In this article, you’ll learn how to implement a multithreaded web server from scratch using only the Rust standard library.
1. Project Setup
Start with a new Rust project:
cargo new rust_web_server
cd rust_web_server
2. Reading and Responding to HTTP Requests
Edit src/main.rs
to include basic TCP listening and response logic:
use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};
use std::thread;
use std::fs;
fn handle_connection(mut stream: TcpStream) {
let mut buffer = [0; 1024];
stream.read(&mut buffer).unwrap();
let contents = fs::read_to_string("hello.html").unwrap();
let response = format!(
"HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}",
contents.len(),
contents
);
stream.write(response.as_bytes()).unwrap();
stream.flush().unwrap();
}
3. Adding a Thread Pool
To handle requests concurrently, we'll build a basic thread pool without any external dependencies:
use std::sync::{mpsc, Arc, Mutex};
struct ThreadPool {
workers: Vec,
sender: mpsc::Sender,
}
type Job = Box;
impl ThreadPool {
fn new(size: usize) -> ThreadPool {
let (sender, receiver) = mpsc::channel();
let receiver = Arc::new(Mutex::new(receiver));
let mut workers = Vec::with_capacity(size);
for id in 0..size {
workers.push(Worker::new(id, Arc::clone(&receiver)));
}
ThreadPool { workers, sender }
}
fn execute(&self, f: F)
where
F: FnOnce() + Send + 'static,
{
self.sender.send(Box::new(f)).unwrap();
}
}
struct Worker {
id: usize,
thread: Option>,
}
impl Worker {
fn new(id: usize, receiver: Arc>>) -> Worker {
let thread = thread::spawn(move || loop {
let job = receiver.lock().unwrap().recv().unwrap();
println!("Worker {} got a job; executing.", id);
job();
});
Worker {
id,
thread: Some(thread),
}
}
}
4. Wiring It All Together
fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
let pool = ThreadPool::new(4);
for stream in listener.incoming().take(10) {
let stream = stream.unwrap();
pool.execute(|| {
handle_connection(stream);
});
}
println!("Shutting down server.");
}
5. Testing
Create a file named hello.html
in your project root:
Rust Web Server
Hello from Rust!
Conclusion
This is a barebones but fully functioning multithreaded web server written entirely with the Rust standard library. From here, you can explore features like routing, middleware, and async IO using more advanced tools like tokio
or hyper
.
If this post helped you, consider supporting me: buymeacoffee.com/hexshift