请参见下面的代码.

fn listen() {
    let listener = TcpListener::bind("127.0.0.1:3000").unwrap();
    
    for stream in listener.incoming() {
        let mut stream = stream.unwrap();
        let mut data_buf = Vec::new();

        stream.read_to_end(&mut data_buf).unwrap(); // Stream read
            
        println!("{}", String::from_utf8(data_buf).unwrap());

        stream.write_all(get_http_response().as_bytes()).unwrap();
    }
}

fn get_http_response() -> String {
    let status_line = "HTTP/1.1 200 OK";
    let contents = "<!DOCTYPE html>
    <html lang=\"en\">
      <head>
        <meta charset=\"utf-8\">
        <title>Poda thendi!</title>
      </head>
      <body>
        <h1>Poda thendi!</h1>
        <p>Hi from Rust</p>
      </body>
    </html>";
    let length = contents.len();

    format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}")
}

现在,如果我在浏览器上访问127.0.0.1:3000,它会显示挂起状态.

但是如果我删除"Stream Read"行,它就会正常工作.为什么?

推荐答案

stream.read_to_end(...)

read_to_end期望浏览器在请求完成后关闭连接(或至少关闭以进行写入).这是因为除了关闭以进行写入(即,发送FIN)之外,对于TCP连接,没有其他类型的信令"End".

但是,浏览器不会在请求后关闭/关闭连接.相反,它将保持打开状态以读取响应,并可能通过同一个TCP连接发送更多请求.这就是为什么它会简单地挂在您的代码中,而永远不会到达它可以编写答案的部分.因此,浏览器也会挂起,因为它永远得不到响应.

而不是使用read_to_end,您需要实际读取数据块并解析这些数据以检测请求的结束.为此,您需要了解HTTP的消息格式-参见the standard.

Rust相关问答推荐

go 掉包装 struct 中的泛型

在函数内定义impl和在函数外定义impl的区别

文档示例需要导入相关的 struct ,但仅在运行测试时.这是故意的行为吗?

在Rust中宏的表达式中提取对象

如何格式化传入Rust中mysql crate的Pool::new的字符串

将数组转换为HashMap的更简单方法

为什么';t std::cell::ref使用引用而不是非空?

在Rust中声明和定义一个 struct 体有什么区别

为什么`str`类型可以是任意大小(未知大小),而`string`类型的大小应该是已知的?

在Rust内联程序集中使用字符串常量

为什么 vec![Vec::with_capacity(n)] 为子向量创建 0 容量?

Cargo.toml:如何有条件地启用依赖项功能?

如何在 Rust 的 Hyper 异步闭包中从外部范围正确读取字符串值

使用 `clap` 在 Rust CLI 工具中设置布尔标志

Rust 引用元组和引用元组

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

有没有办法阻止 rust-analyzer 使非活动代码变暗?

如何从 Rust 中不同类型的多个部分加入 Path?

在特征中返回一个 Self 类型的值

为什么 Bevy 的 Trait 边界不满足 Rapier 物理插件?