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

Boost.Asio实现HTTP服务器解析请求头后读取body阻塞问题求助

问题排查与修复方案

核心问题点

  • read_left_over方法使用input_stream >> extra_data读取streambuf剩余数据存在逻辑错误:>>流操作符默认跳过前导空白符,且遇到空白符就终止读取,会丢失body开头的有效数据,同时无法读全streambuf中已有的全部body数据。如果完整body已经随请求头一起被async_read_until读到本地缓存,计算得到的剩余待读bytes值大于0但客户端已经无数据可发,调用async_read_some就会永久等待。
  • read_body方法中通过lambda捕获req的左值引用,如果req是栈上临时变量,回调触发时会出现引用悬空,引发未定义行为。
  • async_read_some的回调未处理ec错误码,如果发生连接断开、读错误等异常,回调直接无响应,表象就是程序卡住。
  • 未确认io_context运行状态:如果io_context已经停止运行,或者运行io_context的线程被阻塞,异步回调永远不会被调度执行。

修复方案

  1. 替换read_left_over的读取逻辑,直接读取streambuf中所有可用数据,不要使用>>操作符:
void Connection::read_left_over(std::string &req, size_t &bytes) {
  size_t avail = input_stream.available();
  if (avail > 0) {
    std::string extra_data(avail, '\0');
    input_stream.read(&extra_data[0], avail);
    size_t read_len = std::min(avail, bytes);
    req.append(extra_data.data(), read_len);
    bytes -= read_len;
  }
}
  1. 调用internal_read_body之前先判断剩余bytes是否为0,如果已经读完直接调用回调,不需要发起异步读。
  2. 在async_read_some的回调开头增加错误码处理逻辑:
if (ec) {
  error::print(ec);
  return;
}
  1. 确认io_context全程处于运行状态,没有被stop调用终止,也没有被其他阻塞逻辑占满运行线程。

调试方法

  • 打印read_left_over执行后剩余的bytes值、extra_data的长度与内容,确认是否已经读完全部body。
  • 用tcpdump/wireshark抓包确认客户端是否发送了完整的、长度与Content-Length匹配的body数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 05:27:02