26-最终项目:HTTP 服务器

最终项目:HTTP 服务器

译文 · 基于 Asynchronous Programming in Rust

最终项目:HTTP 服务器

原文链接: https://rust-lang.github.io/async-book/09_example/00_intro.html

本章我们将使用异步 Rust 修改 Rust 书中的单线程 Web 服务器,以并发地服务请求。

回顾

以下是课程结束时代码的样子。

src/main.rs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
use std::fs;
use std::io::prelude::*;
use std::net::TcpListener;
use std::net::TcpStream;

fn main() {
    // 在 localhost 7878 端口监听传入的 TCP 连接
    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();

    // 永久阻塞,处理到达此 IP 地址的每个请求
    for stream in listener.incoming() {
        let stream = stream.unwrap();

        handle_connection(stream);
    }
}

fn handle_connection(mut stream: TcpStream) {
    // 从流中读取前 1024 字节数据
    let mut buffer = [0; 1024];
    stream.read(&mut buffer).unwrap();

    let get = b"GET / HTTP/1.1\r\n";

    // 根据请求数据回复问候或 404,
    // 取决于请求中的数据
    let (status_line, filename) = if buffer.starts_with(get) {
        ("HTTP/1.1 200 OK\r\n\r\n", "hello.html")
    } else {
        ("HTTP/1.1 404 NOT FOUND\r\n\r\n", "404.html")
    };
    let contents = fs::read_to_string(filename).unwrap();

    // 将响应写回流,
    // 并刷新流以确保响应发回客户端
    let response = format!("{status_line}{contents}");
    stream.write_all(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}

hello.html:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello!</title>
  </head>
  <body>
    <h1>Hello!</h1>
    <p>Hi from Rust</p>
  </body>
</html>

404.html:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello!</title>
  </head>
  <body>
    <h1>Oops!</h1>
    <p>Sorry, I don't know what you're asking for.</p>
  </body>
</html>

若用 cargo run 运行服务器并在浏览器中访问 127.0.0.1:7878,你会收到 Ferris 的友好问候!


26.1-运行异步代码

运行异步代码

26.2-并发处理连接

并发处理连接

26.3-测试服务器

测试服务器

最后修改 August 23, 2026: 更新 (499855b16)