使用boost/beast时异步HTTPS请求卡在async_write的问题排查
问题分析与解决
核心原因:IO上下文不匹配
代码卡在async_write的直接原因是**ssl_stream_使用类成员io_context_初始化,但协程却绑定到了局部创建的io_context ioc**。
Boost.Asio中,所有异步操作的完成处理器都会提交到对象(如ssl_stream)构造时指定的io_context执行队列。你在协程中调用http::async_write时,操作的完成处理器会被发送到ssl_stream_关联的io_context_,而非局部的ioc。但代码仅调用了ioc.run(),从未运行io_context_,导致异步操作的事件无法被处理,协程因此停滞。
修复方案
使用ssl_stream_关联的io_context_运行协程,而非创建新的局部io_context。修改后的代码如下:
std::optional<boost::beast::http::response<boost::beast::http::dynamic_body>> httpsClass::sendHttpsRequestAndGetResponse ( const boost::beast::http::request<boost::beast::http::string_body> &request) { try{ beast::flat_buffer buffer; http::response<http::dynamic_body> res; beast::get_lowest_layer(*ssl_stream_).expires_after(kTimeout); // 使用类成员的io_context_而非局部ioc boost::asio::spawn(io_context_, [&, this](boost::asio::yield_context yield) { // 按值捕获request,避免生命周期风险(可选但更安全) auto sent = http::async_write(this->ssl_stream_.value(), request, yield); auto received = http::async_read(this->ssl_stream_.value(), buffer, res, yield); }); // 运行ssl_stream_关联的io_context_ io_context_.run(); // 若io_context_后续需复用,调用restart重置状态 io_context_.restart(); return res; } catch (const std::exception &e) { log("Error sending/receiving:{}", e.what()); return std::nullopt; } }
额外注意事项
- IO上下文复用:若
io_context_被类的其他方法或线程共享,需使用boost::asio::strand确保协程串行执行,避免竞态条件。 - 超时机制生效:
expires_after依赖io_context的事件循环,只有运行io_context_才能触发超时逻辑。 - 对象生命周期:确保
ssl_stream_、request等对象在异步操作期间保持有效,按值捕获request到协程中是更安全的做法。
内容的提问来源于stack exchange,提问作者Zohar81
相关产品推荐
相关产品推荐

