长安的 Rust 入门教程长安的 Rust 入门教程
首页
基础教程
进阶内容
Rust 官网
编程指南
首页
基础教程
进阶内容
Rust 官网
编程指南
  • 基础教程

    • 📚 基础教程
    • 第1章 - 认识 Rust
    • 第2章 - 安装 Rust
    • 第3章 - Hello World
    • 第4章 - 变量与可变性
    • 第5章 - 数据类型
    • /guide/06-functions.html
    • 第7章 - 控制流
    • 第8章 - 所有权
    • 第9章 - 引用与借用
    • 第10章 - 结构体
    • 第11章 - 枚举
    • 第12章 - 模式匹配
    • 第13章 - 错误处理
    • 第14章 - 集合类型
    • 第15章 - 模块系统
  • 实战项目

    • 第16章 - 实战项目:猜数字游戏
    • 第17章 - 实战项目:待办事项 CLI
    • 第18章 - 实战项目:简单 HTTP 服务器

第18章 - 实战项目:简单 HTTP 服务器

嗨,朋友!我是长安。

这一章我们要做一个简单的 HTTP 服务器,能够处理 HTTP 请求并返回网页!

这个项目会用到:TCP 连接、多线程、文件读取、HTTP 协议等知识。

🎯 项目目标

制作一个简单的 HTTP 服务器,支持:

  • ✅ 处理 GET 请求
  • ✅ 返回 HTML 页面
  • ✅ 返回 404 错误页面
  • ✅ 多线程处理请求

🚀 创建项目

cargo new http_server
cd http_server

💻 完整代码

src/main.rs:

use std::fs;
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};
use std::thread;
use std::time::Duration;

fn main() {
    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
    println!("🚀 服务器启动成功!");
    println!("📍 访问: http://127.0.0.1:7878");
    println!("按 Ctrl+C 停止服务器\n");

    for stream in listener.incoming() {
        let stream = stream.unwrap();

        // 为每个连接创建一个新线程
        thread::spawn(|| {
            handle_connection(stream);
        });
    }
}

fn handle_connection(mut stream: TcpStream) {
    let mut buffer = [0; 1024];
    stream.read(&mut buffer).unwrap();

    // 解析请求
    let request = String::from_utf8_lossy(&buffer[..]);
    let request_line = request.lines().next().unwrap_or("");

    println!("📨 收到请求: {}", request_line);

    let (status_line, filename) = if request_line.starts_with("GET / HTTP") {
        ("HTTP/1.1 200 OK", "index.html")
    } else if request_line.starts_with("GET /about HTTP") {
        ("HTTP/1.1 200 OK", "about.html")
    } else if request_line.starts_with("GET /slow HTTP") {
        // 模拟慢速请求
        thread::sleep(Duration::from_secs(5));
        ("HTTP/1.1 200 OK", "index.html")
    } else {
        ("HTTP/1.1 404 NOT FOUND", "404.html")
    };

    // 读取 HTML 文件
    let contents = fs::read_to_string(filename).unwrap_or_else(|_| {
        String::from("<h1>文件未找到</h1>")
    });

    // 构建 HTTP 响应
    let response = format!(
        "{}\r\nContent-Length: {}\r\nContent-Type: text/html; charset=utf-8\r\n\r\n{}",
        status_line,
        contents.len(),
        contents
    );

    stream.write_all(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}

📄 创建 HTML 文件

index.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Rust HTTP 服务器</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }
        .container {
            background: rgba(255, 255, 255, 0.1);
            padding: 30px;
            border-radius: 10px;
            backdrop-filter: blur(10px);
        }
        h1 { text-align: center; }
        a {
            color: #ffd700;
            text-decoration: none;
            font-weight: bold;
        }
        a:hover { text-decoration: underline; }
        .nav {
            text-align: center;
            margin: 20px 0;
        }
        .nav a {
            margin: 0 15px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🦀 欢迎来到 Rust HTTP 服务器!</h1>
        <p style="text-align: center; font-size: 1.2em;">
            这是一个用 Rust 编写的简单 HTTP 服务器示例。
        </p>
        
        <div class="nav">
            <a href="/">首页</a>
            <a href="/about">关于</a>
            <a href="/slow">慢速页面</a>
        </div>

        <h2>✨ 特性</h2>
        <ul>
            <li>✅ 处理 HTTP GET 请求</li>
            <li>✅ 返回 HTML 页面</li>
            <li>✅ 404 错误处理</li>
            <li>✅ 多线程并发处理</li>
        </ul>

        <h2>📚 技术栈</h2>
        <ul>
            <li>Rust 标准库</li>
            <li>TCP Socket</li>
            <li>多线程</li>
            <li>HTTP 协议</li>
        </ul>

        <p style="text-align: center; margin-top: 30px;">
            <small>由长安的 Rust 教程提供 🚀</small>
        </p>
    </div>
</body>
</html>

about.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>关于 - Rust HTTP 服务器</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
            color: white;
        }
        .container {
            background: rgba(255, 255, 255, 0.1);
            padding: 30px;
            border-radius: 10px;
            backdrop-filter: blur(10px);
        }
        h1 { text-align: center; }
        a {
            color: #ffd700;
            text-decoration: none;
            font-weight: bold;
        }
        a:hover { text-decoration: underline; }
        .back {
            text-align: center;
            margin-top: 30px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>📖 关于这个项目</h1>
        
        <h2>项目简介</h2>
        <p>
            这是一个使用 Rust 编写的简单 HTTP 服务器,用于演示 Rust 的网络编程能力。
        </p>

        <h2>实现功能</h2>
        <ul>
            <li>TCP Socket 监听</li>
            <li>HTTP 请求解析</li>
            <li>静态文件服务</li>
            <li>多线程并发</li>
        </ul>

        <h2>技术亮点</h2>
        <ul>
            <li>🚀 零依赖,只用标准库</li>
            <li>⚡ 多线程处理,支持并发</li>
            <li>🛡️ 类型安全,编译时检查</li>
            <li>💪 性能优异,内存安全</li>
        </ul>

        <div class="back">
            <a href="/">← 返回首页</a>
        </div>
    </div>
</body>
</html>

404.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>404 - 页面未找到</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 50px auto;
            padding: 20px;
            background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
            color: white;
            text-align: center;
        }
        .container {
            background: rgba(255, 255, 255, 0.1);
            padding: 30px;
            border-radius: 10px;
            backdrop-filter: blur(10px);
        }
        h1 { font-size: 5em; margin: 0; }
        h2 { margin-top: 0; }
        a {
            color: #ffd700;
            text-decoration: none;
            font-weight: bold;
            font-size: 1.2em;
        }
        a:hover { text-decoration: underline; }
    </style>
</head>
<body>
    <div class="container">
        <h1>404</h1>
        <h2>😱 页面未找到</h2>
        <p>抱歉,你访问的页面不存在。</p>
        <p style="margin-top: 30px;">
            <a href="/">← 返回首页</a>
        </p>
    </div>
</body>
</html>

📖 代码详解

1. 启动服务器

let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
  • 在本地 7878 端口监听 TCP 连接
  • 127.0.0.1 是本地回环地址

2. 接受连接

for stream in listener.incoming() {
    let stream = stream.unwrap();
    thread::spawn(|| {
        handle_connection(stream);
    });
}
  • incoming() 返回连接迭代器
  • 为每个连接创建新线程处理

3. 解析 HTTP 请求

let mut buffer = [0; 1024];
stream.read(&mut buffer).unwrap();

let request = String::from_utf8_lossy(&buffer[..]);
let request_line = request.lines().next().unwrap_or("");
  • 读取请求数据到缓冲区
  • 转换为字符串并提取第一行

4. 路由处理

let (status_line, filename) = if request_line.starts_with("GET / HTTP") {
    ("HTTP/1.1 200 OK", "index.html")
} else if request_line.starts_with("GET /about HTTP") {
    ("HTTP/1.1 200 OK", "about.html")
} else {
    ("HTTP/1.1 404 NOT FOUND", "404.html")
};
  • 根据请求路径选择对应的 HTML 文件

5. 返回 HTTP 响应

let response = format!(
    "{}\r\nContent-Length: {}\r\nContent-Type: text/html; charset=utf-8\r\n\r\n{}",
    status_line,
    contents.len(),
    contents
);

stream.write_all(response.as_bytes()).unwrap();
stream.flush().unwrap();
  • 构建符合 HTTP 协议的响应
  • 写入 TCP 流并发送

🏃 运行服务器

cargo run

输出:

🚀 服务器启动成功!
📍 访问: http://127.0.0.1:7878
按 Ctrl+C 停止服务器

📨 收到请求: GET / HTTP/1.1
📨 收到请求: GET /about HTTP/1.1
📨 收到请求: GET /test HTTP/1.1

然后在浏览器打开 http://127.0.0.1:7878

🎨 改进建议

1. 使用线程池

use std::sync::mpsc;
use std::sync::{Arc, Mutex};

struct ThreadPool {
    workers: Vec<Worker>,
    sender: mpsc::Sender<Job>,
}

type Job = Box<dyn FnOnce() + Send + 'static>;

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<F>(&self, f: F)
    where
        F: FnOnce() + Send + 'static,
    {
        let job = Box::new(f);
        self.sender.send(job).unwrap();
    }
}

2. 添加静态文件服务

fn serve_file(path: &str) -> Option<Vec<u8>> {
    fs::read(format!("static/{}", path)).ok()
}

3. 添加 MIME 类型支持

fn get_content_type(path: &str) -> &str {
    if path.ends_with(".html") {
        "text/html"
    } else if path.ends_with(".css") {
        "text/css"
    } else if path.ends_with(".js") {
        "application/javascript"
    } else if path.ends_with(".jpg") || path.ends_with(".jpeg") {
        "image/jpeg"
    } else {
        "text/plain"
    }
}

💡 学到的知识点

通过这个项目,我们学会了:

  • ✅ TCP Socket 编程
  • ✅ HTTP 协议基础
  • ✅ 多线程处理
  • ✅ 文件 I/O
  • ✅ 字符串处理
  • ✅ 模式匹配

💪 挑战任务

  1. 实现 POST 请求处理
  2. 添加日志记录功能
  3. 支持静态文件目录
  4. 实现简单的路由系统
  5. 添加基本的身份验证
POST 请求处理示例
fn handle_post(stream: &mut TcpStream, body: &str) {
    println!("收到 POST 数据: {}", body);
    
    let response = "HTTP/1.1 200 OK\r\n\r\n收到数据";
    stream.write_all(response.as_bytes()).unwrap();
}

// 在 handle_connection 中:
if request_line.starts_with("POST") {
    // 提取请求体
    let body_start = request.find("\r\n\r\n").unwrap_or(0) + 4;
    let body = &request[body_start..];
    handle_post(&mut stream, body);
}

🚀 进阶学习

想要更强大的 Web 框架?可以学习:

  • Actix-web:高性能 Web 框架
  • Rocket:易用的 Web 框架
  • Axum:基于 Tokio 的异步框架
  • Warp:组合式 Web 框架

🎉 总结

恭喜你完成了三个实战项目!

你已经学会了:

  • 🎮 猜数字游戏 - 基础语法实践
  • 📝 待办事项 CLI - 文件操作和数据结构
  • 🌐 HTTP 服务器 - 网络编程和并发

现在你已经掌握了 Rust 的基础知识和实践经验!

准备好挑战更高级的内容了吗?进阶教程包含:泛型、Trait、生命周期、智能指针和并发编程!

进入进阶教程 →


继续加油,用 Rust 创造更多精彩的项目吧!🚀

最近更新: 2025/12/26 18:01
Contributors: 王长安
Prev
第17章 - 实战项目:待办事项 CLI