Rust TcpStream 读后不能写,但可以不读而写。为什么?

Man*_*man 1 rust

请参阅下面的代码。

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}")
}

Run Code Online (Sandbox Code Playgroud)

现在,如果我在浏览器上访问 127.0.0.1:3000,它会显示待处理状态。

但如果我删除“Stream read”行,它就会按预期工作。为什么?

Ste*_*ich 5

stream.read_to_end(...)
Run Code Online (Sandbox Code Playgroud)

read_to_end期望浏览器在请求完成后关闭连接(或至少关闭写入)。因为对于 TCP 连接来说,除了关闭写入(即发送 FIN)之外,没有其他类型的信号“结束”。

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

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