云计算百科
云计算领域专业知识百科平台

C++ 协程式 TCP 网络服务框架:构建高并发 Echo 与多人聊天室服务器

一、引言:为何用协程写网络服务?

传统 C++ 网络服务器一般使用如下方式:

  • select() 或 epoll() + 状态机

  • 多线程 per-connection(线程爆炸问题)

  • Boost.Asio(复杂回调嵌套)

C++20 协程带来非阻塞、无回调、简洁清晰的异步 IO 编程方式。我们可以构建一个轻量的协程式 TCP 网络服务器框架,支持数百甚至上千并发连接,逻辑简洁,性能优异。


二、本文目标

实现一个协程驱动的网络服务框架,具备以下特性:

功能描述
协程处理客户端连接 每个连接由一个协程处理,避免线程堆叠
非阻塞读写封装 使用协程挂起等待 socket 读写
Echo 模式 客户端发什么就回什么
聊天室模式(支持切换) 所有连接共享广播消息
连接生命周期管理 自动关闭、错误处理、防崩溃
支持 Linux 平台原生 epoll 使用 epoll 驱动 socket 与协程调度

三、整体架构图

lua

复制编辑

+—————————+ | TCP 监听器 | +—————————+ | +—–v—–+ | 新连接协程 | —> 创建 Client 协程 +—–+—–+ | +———v———-+ +———+ | Client 协程 | <—> | socket | | 读写消息 + 广播 | +———+ +——————–+


四、基础模块一览

模块文件作用
socket.hpp socket API 封装
awaitable.hpp 协程等待封装(read/write)
server.hpp 主服务器控制器
client.hpp 客户端协程控制器
epoll_loop.hpp epoll 驱动事件分发与 resume

五、epoll 协程等待实现核心思想

cpp

复制编辑

// 伪代码结构 co_await socket_read(sockfd, buffer, len); // 1. 注册 sockfd 到 epoll // 2. 协程挂起,等待 IO 就绪 // 3. epoll 返回后 resume 协程

这类似于 async/await 的异步 IO 模型,但是我们自己用 C++20 原语构建的。


六、Awaitable 封装(以 read 为例)

cpp

复制编辑

struct ReadAwaiter { int fd; char* buffer; size_t length; ssize_t result; ReadAwaiter(int fd, char* buf, size_t len) : fd(fd), buffer(buf), length(len), result(0) {} bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle<> h) { register_epoll_read(fd, h); // 注册读事件 } ssize_t await_resume() const noexcept { return result; } };

你需要维护一个 epoll_loop 循环来监听所有挂起的 fd 与协程 resume。


七、Socket API 简化封装

cpp

复制编辑

int create_server_socket(int port) { int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); int opt = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); sockaddr_in addr = {AF_INET, htons(port), INADDR_ANY}; bind(sockfd, (sockaddr*)&addr, sizeof(addr)); listen(sockfd, SOMAXCONN); return sockfd; }


八、客户端协程逻辑:Echo 模式

cpp

复制编辑

Task<> handle_client(int client_fd) { char buf[1024]; try { while (true) { ssize_t n = co_await ReadAwaiter(client_fd, buf, sizeof(buf)); if (n <= 0) break; std::cout << "[client] 收到: " << std::string(buf, n) << "\\n"; ssize_t m = write(client_fd, buf, n); // 简化写 if (m <= 0) break; } } catch (…) { std::cout << "[client] 异常断开\\n"; } close(client_fd); co_return; }


九、聊天室支持:共享广播池

cpp

复制编辑

std::set<int> all_clients; std::mutex client_mtx; void broadcast_to_all(const std::string& msg, int exclude = -1) { std::lock_guard<std::mutex> lock(client_mtx); for (int fd : all_clients) { if (fd == exclude) continue; write(fd, msg.c_str(), msg.size()); } }

替换上面的 write() 为:

cpp

复制编辑

broadcast_to_all(std::string(buf, n), client_fd);


十、协程主监听器

cpp

复制编辑

Task<> server_loop(int listen_fd) { while (true) { int client_fd = accept(listen_fd, nullptr, nullptr); if (client_fd >= 0) { fcntl(client_fd, F_SETFL, O_NONBLOCK); { std::lock_guard<std::mutex> lock(client_mtx); all_clients.insert(client_fd); } handle_client(client_fd).start(); // 协程化处理 } else { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } }


十一、epoll 协程事件调度核心(伪码)

你需要维护如下结构:

cpp

复制编辑

std::unordered_map<int, std::coroutine_handle<>> read_waiters; void register_epoll_read(int fd, std::coroutine_handle<> h) { read_waiters[fd] = h; epoll_ctl(epfd, EPOLL_CTL_ADD, fd, …); }

在 epoll_wait() 中:

cpp

复制编辑

for (each ready fd) { auto h = read_waiters[fd]; if (h) h.resume(); read_waiters.erase(fd); }


十二、主函数入口

cpp

复制编辑

int main() { int port = 9000; int listen_fd = create_server_socket(port); std::cout << "服务器监听端口:" << port << "\\n"; server_loop(listen_fd).start(); // 启动 epoll 主循环(需要另开线程) epoll_loop(); // 持续调度挂起协程 return 0; }


十三、运行测试

你可以使用多个 telnet 客户端测试:

bash

复制编辑

telnet 127.0.0.1 9000

Echo 模式:

复制编辑

客户端发送:hello 服务器回应:hello

聊天室模式:

复制编辑

客户端1:hello 客户端2:hello(来自客户端1)


十四、性能与优势

特性优势说明
低开销 协程调度无需线程切换
高并发 可轻松支持上千连接
可读性强 逻辑结构顺序直观,避免回调地狱
易于扩展 模块清晰,可加入加密、验证、协议处理等

十五、扩展建议

功能项实现方式简述
WebSocket 支持 封装帧协议并改写 read/write 协程
用户身份识别 在连接协程中添加认证阶段
JSON 协议封装 结合 nlohmann/json 解析客户端消息
REST + Chat 服务 HTTP 与聊天室服务共用端口,路径区分
TLS 加密支持 使用 OpenSSL 配合非阻塞 BIO 封装协程 I/O

十六、总结

本项目实现了:

  • 一个基于 C++ 协程的 TCP 网络服务框架

  • 每个客户端由协程独立处理

  • 支持 Echo 模式与聊天室广播模式

  • 使用 epoll 驱动异步协程调度

  • 构建了基础的协程式高并发网络模型

赞(0)
未经允许不得转载:网硕互联帮助中心 » C++ 协程式 TCP 网络服务框架:构建高并发 Echo 与多人聊天室服务器
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!