使用Asio发送基础HTTP请求无响应,但tcpdump显示有返回
问题分析
从抓包日志能明确看到问题根源:
- 程序发送完请求后立刻发送了FIN包关闭写端,随后服务器返回响应时,本地已发送RST包,说明程序已经退出,socket被销毁。
- 代码中调用
socket.available()时,服务器响应还未到达本地缓冲区,返回值为0,导致后续读取逻辑直接跳过,程序提前退出。
同时代码存在两个潜在风险:
write_some无法保证一次性发送全部请求数据,极端情况下会导致请求不完整。- 依赖
available()判断是否有响应是不可靠的,网络延迟会导致响应滞后到达。
修复方案
确保请求完整发送
用asio::write替代write_some,它会阻塞直到所有数据发送完成:asio::write(socket, asio::buffer(sRequest), ec);正确读取响应
移除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
相关产品推荐
相关产品推荐

