C++ 使用asio协程搭建异步服务器的过程
2026/8/11 1:43:11 网站建设 项目流程

协程核心定义

协程是用户态轻量级执行单元,能在执行中主动暂停(挂起)并保留上下文,待条件满足后恢复执行,切换开销远低于线程;在你的Boost.Asio代码中,协程通过co_await等待异步IO(如读取客户端数据),挂起时不阻塞线程,IO完成后自动恢复,让异步代码像同步代码一样易读。

实现:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

#include <iostream>

// 引入Boost.Asio协程相关头文件

#include<boost/asio/co_spawn.hpp> // 协程创建函数

#include<boost/asio/detached.hpp> // 协程分离执行标识

#include<boost/asio/io_context.hpp> // IO上下文(事件循环)

#include<boost/asio/ip/tcp.hpp> // TCP相关功能

#include<boost/asio/signal_set.hpp> // 信号处理

#include<boost/asio/write.hpp> // 异步写操作

// 简化常用的Boost.Asio协程相关类型/函数名

usingboost::asio::ip::tcp;

usingboost::asio::awaitable;// 协程返回类型

usingboost::asio::co_spawn;// 启动协程的函数

usingboost::asio::detached;// 协程分离执行(不等待完成)

usingboost::asio::use_awaitable;// 异步操作适配协程的等待令牌

// 协程本地上下文命名空间别名,用于获取当前协程的执行器

namespacethis_coro = boost::asio::this_coro;

// 协程函数:处理单个客户端的回显逻辑

// 参数:已连接的TCP套接字(通过移动语义传递,避免拷贝)

// 返回值:awaitable<void> 表示这是一个可等待的协程任务

awaitable<void>echo(tcp::socket socket)

{

try{

chardata[1024];// 数据接收缓冲区,大小1024字节

// 无限循环处理客户端数据,直到连接断开/异常

for(;;)

{

// 异步读取客户端发送的数据,协程挂起等待数据到达

// co_await:等待异步操作完成,期间不阻塞线程

// async_read_some:读取任意长度的数据到缓冲区,返回实际读取的字节数

std::size_tn = co_await socket.async_read_some(boost::asio::buffer(data), use_awaitable);

// 异步将读取到的数据原样回写给客户端,同样通过co_await等待写完成

co_await async_write(socket, boost::asio::buffer(data, n), use_awaitable);

}

}

catch(std::exception& e)

{

// 捕获连接断开、网络异常等错误,打印异常信息

std::cout <<"回显协程异常: "<< e.what() << std::endl;

}

}

// 协程函数:TCP服务器监听逻辑,等待客户端连接

awaitable<void>listener()

{

// 获取当前协程绑定的执行器(调度器),用于后续创建接收器/套接字

auto executor = co_await this_coro::executor;

// 创建TCP接收器,绑定到指定执行器,监听IPv4的10086端口

tcp::acceptor acceptor(executor, { tcp::v4(), 10086 });

// 无限循环等待客户端连接

for(;;)

{

// 异步等待客户端接入,协程挂起,有新连接时返回已连接的套接字

tcp::socket socket = co_await acceptor.async_accept(use_awaitable);

// 启动新的协程处理该客户端的回显逻辑

// detached:新协程独立执行,不阻塞当前监听协程

// std::move:转移套接字所有权到echo协程

co_spawn(executor, echo(std::move(socket)), detached);

}

}

intmain()

{

try{

// 创建IO上下文,参数1表示用1个线程运行事件循环

boost::asio::io_context io_context(1);

// 定义信号集,监听SIGINT(Ctrl+C)和SIGTERM(进程终止)信号

boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);

// 异步等待信号触发,收到信号后停止IO上下文,优雅退出程序

signals.async_wait([&](auto, auto)

{

io_context.stop();

});

// 启动监听协程,detached表示协程后台运行,不阻塞main函数

co_spawn(io_context, listener(), detached);

// 运行IO上下文的事件循环,处理所有异步操作和协程任务

io_context.run();

}

catch(std::exception& e)

{

// 捕获服务器启动阶段的异常(如端口被占用),打印错误信息

std::cout <<"主程序异常: "<< e.what() << std::endl;

}

return0;

}

总结

  1. 协程核心特性:可暂停、可恢复、用户态调度、低开销
  2. 代码中体现:awaitable标记协程函数,co_await实现挂起等待,依托io_context完成调度。
  3. 核心价值:用同步写法实现异步IO,避免回调嵌套,提升代码可读性和并发效率。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询