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

使用Asio发送基础HTTP请求无响应,但tcpdump显示有返回

问题分析

从抓包日志能明确看到问题根源:

  • 程序发送完请求后立刻发送了FIN包关闭写端,随后服务器返回响应时,本地已发送RST包,说明程序已经退出,socket被销毁。
  • 代码中调用socket.available()时,服务器响应还未到达本地缓冲区,返回值为0,导致后续读取逻辑直接跳过,程序提前退出。

同时代码存在两个潜在风险:

  • write_some无法保证一次性发送全部请求数据,极端情况下会导致请求不完整。
  • 依赖available()判断是否有响应是不可靠的,网络延迟会导致响应滞后到达。

修复方案

  1. 确保请求完整发送
    用asio::write替代write_some,它会阻塞直到所有数据发送完成:

    asio::write(socket, asio::buffer(sRequest), ec);
    
  2. 正确读取响应
    移除available()检查,直接用read_some循环读取数据,直到服务器关闭连接(因为请求中设置了Connection: close):

    std::vector<char> vBuffer(1024);
    while (socket.is_open()) {
        std::size_t bytes_read = socket.read_some(asio::buffer(vBuffer), ec);
        if (ec == asio::error::eof) {
            break; // 服务器关闭连接,读取完成
        } else if (ec) {
            std::cerr << "读取错误: " << ec.message() << '\n';
            break;
        }
        std::cout.write(vBuffer.data(), bytes_read);
    }
    

完整修复代码

#include<json/json.h>
#include<asio/ts/buffer.hpp>
#include<asio/ts/internet.hpp>
#include<iostream>

#define ASIO_STANDALONE

int main(){
    asio::error_code ec;
    asio::io_context context;
    asio::ip::tcp::endpoint endpoint(asio::ip::make_address("93.184.216.34", ec), 80);
    asio::ip::tcp::socket socket(context);
    socket.connect(endpoint, ec);
    
    std::cout << ec.message() << '\n';

    if(socket.is_open())
    {
        std::string sRequest = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n";
        std::cout << sRequest;
        // 确保请求全部发送
        asio::write(socket, asio::buffer(sRequest), ec);
        if (ec) {
            std::cerr << "发送错误: " << ec.message() << '\n';
            return 1;
        }
    
        std::vector<char> vBuffer(1024);
        // 循环读取直到连接关闭
        while (socket.is_open()) {
            std::size_t bytes_read = socket.read_some(asio::buffer(vBuffer), ec);
            if (ec == asio::error::eof) {
                break;
            } else if (ec) {
                std::cerr << "读取错误: " << ec.message() << '\n';
                break;
            }
            std::cout.write(vBuffer.data(), bytes_read);
        }
    }

    return 0;
}

关键说明

  • 同步模式下read_some会阻塞直到有数据可读,不需要提前检查缓冲区状态。
  • Connection: close头告诉服务器发送完响应后关闭连接,因此可以通过检测eof错误来判断响应读取完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:35:36