我有一个同步方法,它使用http::write
发送https请求,然后使用http::read
读取它的响应。
然而,为了增加超时,我不得不在我的方法中转移到异步调用,所以我尝试使用http::async_read
和http::async_write
,但是保持整个流程同步,这样方法只有在得到https响应时才会返回。
下面是我尝试:
class httpsClass {
std::optional<boost::beast::ssl_stream<boost::beast::tcp_stream>> ssl_stream_;
httpsClass(..) {
// notice that ssl_stream_ is initialized according to io_context_/ctx_
// that are class members that get set by c'tor args
ssl_stream_.emplace(io_context_, ctx_);
}
}
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{
boost::asio::io_context ioc;
beast::flat_buffer buffer;
http::response<http::dynamic_body> res;
beast::get_lowest_layer(*ssl_stream_).expires_after(kTimeout);
boost::asio::spawn(ioc, [&, this](boost::asio::yield_context yield) {
auto sent = http::async_write(this->ssl_stream_.value(), request, yield);
auto received = http::async_read(this->ssl_stream_.value(), buffer, res, yield);
});
ioc.run();// this will finish only once the task above will be fully executed.
return res;
} catch (const std::exception &e) {
log("Error sending/receiving:{}", e.what());
return std::nullopt;
}
}
在试验过程中,上面的方法到达了我为内部io上下文(ioc)分配的任务,但是,它在async_write方法上卡在了这个任务中。
有人能帮我弄清楚为什么它卡住了吗?它会不会和ssl_stream_ is用另一个io上下文对象(io_context_)初始化的事实有关?
1条答案
按热度按时间lqfhib0f1#
ssl_stream_上的完成处理程序的默认执行器是外部io_context,它无法执行,因为您可能没有运行它。
我的建议是:
future<Response>
,而不是optional<Response>
(丢失错误信息)io_context&
,而是传递执行器,如果需要,可以更容易地将其更改为strand
执行器。添加一些代码使其自包含:
您的实现非常接近,除了不必要的服务:
现在,对于任何异步操作来说,
io_service
run()
-ning都是很重要的。对于完全异步的代码,你不需要线程,但是当你阻塞响应时,你会需要线程。最简单的方法是用thread_pool
代替io_service
,thread_pool
会为你做run()
-ning。如您所见,此测试将针对www.example.com运行两个请求https://httpbin.org/#/Dynamic_data/get_delay__delay_。第二个请求将超时,因为5s超过了ssl_stream_上的3s过期时间。
完整演示
**一个
在我的系统上运行: