c++ - 使用协程时 boost::asio 超时的最佳实践
问题描述
下面的连接尝试创建(在我的网络配置上)2 分钟的延迟,因为目标不存在并且地址与我的机器位于不同的子网上。所以我添加了超时逻辑以将尝试限制为 5 秒:
#define BOOST_ASIO_HAS_CO_AWAIT
#define BOOST_ASIO_HAS_STD_COROUTINE
#include <iostream>
#include <chrono>
#include <thread>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/executor_work_guard.hpp>
#include <boost/asio/redirect_error.hpp>
namespace this_coro = boost::asio::this_coro;
using namespace std::chrono_literals;
boost::asio::awaitable<void> fail_to_connect()
{
auto executor = co_await this_coro::executor;
auto socket = boost::asio::ip::tcp::socket{executor};
auto ep = boost::asio::ip::tcp::endpoint{
boost::asio::ip::make_address_v4("192.168.1.52"),
80};
auto timer = boost::asio::steady_timer{executor};
timer.expires_after(5s);
boost::asio::co_spawn(
executor,
[&]() -> boost::asio::awaitable<void> {
auto ec = boost::system::error_code{};
co_await timer.async_wait(boost::asio::redirect_error(boost::asio::use_awaitable, ec));
std::cout << "Thread ID: " << std::this_thread::get_id()
<< " Timer: " << ec.message() << std::endl;
if (!ec) {
socket.close();
}
},
boost::asio::detached
);
std::cout << "Thread ID: " << std::this_thread::get_id()
<< " Starting connection" << std::endl;
co_await boost::asio::async_connect(socket,
std::array{std::move(ep)},
boost::asio::use_awaitable);
timer.cancel();
}
int main()
{
auto ctx = boost::asio::io_context{};
auto guard = boost::asio::make_work_guard(ctx.get_executor());
auto exception_handler = [&](auto e_ptr) {
if (e_ptr) {
std::rethrow_exception(e_ptr);
}
};
boost::asio::co_spawn(ctx, fail_to_connect, std::move(exception_handler));
ctx.run();
}
这按预期工作。从线程 ID 中可以看出,在两个协程之间使用相同的执行上下文意味着我也不会同时访问套接字。
14:58:41: Starting /home/cmannett85/workspace/build-scratch-Desktop-Debug/scratch ...
Thread ID: 140171855615808 Starting connection
Thread ID: 140171855615808 Timer: Success
terminate called after throwing an instance of 'boost::system::system_error'
what(): Operation canceled
14:58:46: The program has unexpectedly finished.
然而,这感觉很笨拙,尤其是与非协程回调样式相比。使用协程是否有更好的超时方法?我正在努力寻找例子。
解决方案
推荐阅读
- javascript - 我需要使用链接文本作为 aria 标签将 aria-label 添加到网站上的所有链接
- jquery - 数据表 Dom 定位引导程序
- c++ - 在使用 std::unique_ptr 在退出作用域块时自动释放内存的情况下,为什么不直接使用堆栈呢?
- checkbox - Semantic-ui 预设复选框状态
- mongodb - 猫鼬 在短语中查找确切的单词
- c# - 我如何将多重断言与 MSTEST (Specflow) 结合起来
- php - 带有负双精度值的 PHP MySQL QUERY
- excel - 将特定数据复制到模板并将其保存为 TXT 文件的宏
- php - 我的 laravel 应用程序没有选择正确的路线
- intellij-idea - InteliJ 中的栏的名称是什么,位于编辑器窗口的底部