0

0

c++如何使用Coroutines TS与Asio结合_c++协程网络编程实践

穿越時空

穿越時空

发布时间:2025-12-06 23:00:08

|

856人浏览过

|

来源于php中文网

原创

使用C++20协程与Asio可简化异步网络编程,通过asio::awaitable和co_await实现同步风格代码。1. 需GCC 10+/Clang 12+并启用-std=c++20;2. Asio 1.20+或Boost.Asio 1.75+支持协程;3. 协程返回类型为asio::awaitable,用co_await等待异步操作;4. co_spawn启动协程并指定执行策略如detached;5. 使用asio::redirect_error避免异常抛出,提升控制粒度;6. 注意避免协程中大栈分配和阻塞调用,应使用asio提供的异步机制。

c++如何使用coroutines ts与asio结合_c++协程网络编程实践

使用 C++ Coroutines TS 与 Asio 进行网络编程,可以极大简化异步操作的编写方式,让异步代码看起来像同步一样清晰。Asio 自 1.20 版本(对应 Boost.Asio 1.75+)开始原生支持 C++20 协程,允许你以现代 C++ 的方式编写高性能异步网络服务。

启用协程支持

确保你的编译环境支持 C++20 并开启协程功能:

  • 使用 GCC 10+ 或 Clang 12+ 编译器
  • 编译选项添加:-std=c++20
  • Asio 需要定义宏:ASIO_ENABLE_HANDLER_TRACKING(可选调试)和确保启用了协程支持(默认已启用)
注意:如果你使用的是 Boost.Asio,需使用 Boost 1.75 及以上版本,并包含头文件时使用 #include

基本协程返回类型:awaitable

在 Asio 中,协程函数返回类型为 asio::awaitable,其中 T 是协程最终返回的值类型(通常为 void)。

一个典型的协程如下:

立即学习C++免费学习笔记(深入)”;

asio::awaitable echo_session(asio::ip::tcp::socket socket) {
  try {
    char data[1024];
    for (;;) {
      std::size_t n = co_await socket.async_read_some(asio::buffer(data), asio::use_awaitable);
      co_await async_write(socket, asio::buffer(data, n), asio::use_awaitable);
    }
  } catch (const std::exception&) {
    // 客户端断开或出错
  }
}

这里的关键是 co_awaitasio::use_awaitable。它告诉 Asio 以协程方式等待异步操作完成,而不是使用回调函数

启动协程服务

你需要一个 asio::io_context 来运行事件循环,并通过协程调度任务。

示例服务器主循环:

沁言学术
沁言学术

你的论文写作AI助理,永久免费文献管理工具,认准沁言学术

下载
asio::awaitable listen_loop(asio::io_context& ioc, unsigned short port) {
  auto executor = ioc.get_executor();
  asio::ip::tcp::acceptor acceptor(executor, {asio::ip::tcp::v4(), port});

  for (;;) {
    asio::ip::tcp::socket socket = co_await acceptor.async_accept(asio::use_awaitable);
    co_spawn(executor, echo_session(std::move(socket)), asio::detached);
  }
}

int main() {
  asio::io_context ioc{1};

  co_spawn(ioc, listen_loop(ioc, 8080), asio::detached);

  ioc.run();
  return 0;
}

说明:

  • co_spawn 用于启动一个协程,第三个参数指定如何处理协程完成(如 asio::detached 表示不关心结果)
  • co_await acceptor.async_accept(...) 暂停协程直到有连接到来
  • 每个新连接通过 co_spawn 启动独立会话,不会阻塞主监听循环

异常处理与资源管理

协程中抛出的异常会被自动捕获并传递给协程框架。建议在顶层协程中捕获异常,避免崩溃。

改进后的 session

asio::awaitable echo_session(asio::ip::tcp::socket socket) {
  try {
    char data[1024];
    while (socket.is_open()) {
      auto [e, n] = co_await socket.async_read_some(
          asio::buffer(data), asio::redirect_error(asio::use_awaitable));

      if (e) break; // 客户端关闭

      auto [write_err] = co_await async_write(
          socket, asio::buffer(data, n), asio::redirect_error(asio::use_awaitable));
      if (write_err) break;
    }
  } catch (...) {
    // 处理未预期异常
  }
}

使用 asio::redirect_error 可将错误码转为元组形式返回,避免抛异常,适合精细控制流程。

优势与注意事项

优点:

  • 代码逻辑清晰,无需嵌套回调
  • 局部变量在 co_await 后依然有效,状态保持自然
  • 易于组合多个异步操作(如认证 + 数据读取)

注意事项:

  • 协程空间有限,避免在协程中分配大对象(可使用堆或传引用)
  • 不要在协程中调用阻塞函数(如 std::this_thread::sleep_for),应使用 asio::steady_timer
  • 协程生命周期由 co_spawn 管理策略决定,detached 下需确保资源安全释放
基本上就这些。结合 Asio 与 C++ 协程,能写出既高效又易维护的网络服务。不复杂但容易忽略细节,比如错误处理和执行器上下文传递。

相关专题

更多
session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

308

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

740

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

88

2025.08.19

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

175

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

97

2025.11.27

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

572

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

392

2023.07.18

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

72

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 3.2万人学习

Excel 教程
Excel 教程

共162课时 | 12.3万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号