You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用原生Rust发送HTTP GET请求无响应的原因是什么?

解决Rust TCP流发送HTTP请求后无法收到响应的问题

你的代码发送请求后一直卡住,核心原因是HTTP/1.1默认启用持久连接(Keep-Alive)——服务器返回响应后不会立刻关闭TCP连接,而read_to_string会一直阻塞等待流关闭,自然无法拿到完整响应。

下面给你几种实用的解决思路:

方法1:添加Connection: close请求头

直接告诉服务器:"返回响应后就关闭连接",这样read_to_string就能读到响应结尾并正常返回:

use std::io::{Read, Result, Write};
use std::net::TcpStream;

fn main() {
    if let Err(err) = connect() {
        println!("err = {}", err);
    }
}

fn connect() -> Result<()> {
    let mut stream = TcpStream::connect("www.google.de:80")?;
    let mut request_data = String::new();
    request_data.push_str("GET / HTTP/1.1");
    request_data.push_str("\r\n");
    request_data.push_str("Host: www.google.de");
    request_data.push_str("\r\n");
    // 新增这行,通知服务器关闭连接
    request_data.push_str("Connection: close");
    request_data.push_str("\r\n");
    request_data.push_str("\r\n");
    
    println!("request_data = {:?}", request_data);
    stream.write_all(request_data.as_bytes())?;
    
    let mut buf = String::new();
    let result = stream.read_to_string(&mut buf)?;
    println!("读取到字节数 = {}", result);
    println!("响应内容:\n{}", buf);
    Ok(())
}

方法2:使用成熟的HTTP客户端库(推荐)

手动处理TCP流和HTTP协议细节很容易踩坑,实际项目里更推荐用reqwest这类专门的HTTP库,它会帮你自动处理连接管理、响应解析等问题:

首先在Cargo.toml中添加依赖:

[dependencies]
reqwest = { version = "0.11", features = ["blocking"] }

然后简化代码:

fn main() {
    if let Err(err) = connect() {
        println!("err = {}", err);
    }
}

fn connect() -> Result<(), reqwest::Error> {
    let response = reqwest::blocking::get("http://www.google.de")?;
    println!("响应状态码: {}", response.status());
    
    let body = response.text()?;
    println!("响应内容:\n{}", body);
    Ok(())
}

方法3:手动解析Content-Length读取响应

如果想深入学习HTTP协议细节,可以自己解析响应头中的Content-Length字段,然后读取指定长度的字节,避免依赖read_to_string的阻塞行为:

use std::io::{BufRead, BufReader, Read, Result, Write};
use std::net::TcpStream;

fn main() {
    if let Err(err) = connect() {
        println!("err = {}", err);
    }
}

fn connect() -> Result<()> {
    let mut stream = TcpStream::connect("www.google.de:80")?;
    let request_data = "GET / HTTP/1.1\r\nHost: www.google.de\r\n\r\n";
    stream.write_all(request_data.as_bytes())?;

    let mut reader = BufReader::new(stream);
    let mut headers = String::new();
    // 读取响应头,直到遇到空行(头和体的分隔符)
    reader.read_line(&mut headers)?;
    while !headers.ends_with("\r\n\r\n") {
        let mut line = String::new();
        reader.read_line(&mut line)?;
        headers.push_str(&line);
    }

    // 从响应头中解析Content-Length
    let content_length: usize = headers
        .lines()
        .find(|line| line.starts_with("Content-Length:"))
        .and_then(|line| line.split_whitespace().nth(1))
        .and_then(|s| s.parse().ok())
        .expect("无法获取Content-Length字段");

    // 读取指定长度的响应体
    let mut body = vec![0; content_length];
    reader.read_exact(&mut body)?;
    let body_str = String::from_utf8_lossy(&body);

    println!("响应头:\n{}", headers);
    println!("响应体:\n{}", body_str);
    Ok(())
}

这种方式适合学习HTTP协议底层逻辑,但日常开发还是优先用现成库更高效。

内容的提问来源于stack exchange,提问作者RSX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:21:55