前言: 这是一个极具前瞻性和工程价值的目标!结合 C++20 协程 、Linux 的 io_uring 与 Windows 的 IOCP ,打造一个真正高性能、跨平台、同步风格编写、异步底层执行 的网络库,正是现代系统编程的“圣杯”之一。
一、项目名称建议(简洁、有技术感、易记)
名称
含义/联想
推荐度
CoroNet
Coroutine + Network,简洁直白
⭐⭐⭐⭐⭐
UringIO
突出 io_uring,但弱化 Windows
⭐⭐
Asyncore
Async + Core,类似 Python asyncio
⭐⭐⭐
NetFiber
Fiber 风格协程 + Net
⭐⭐⭐
CoSocket
协程 Socket,直观
⭐⭐⭐⭐
Aether
“以太”,古希腊中传递信息的媒介,寓意轻盈、高速、无形
⭐⭐⭐⭐⭐(文艺+技术感)
Strand
意为“线束”,隐喻协程流 + I/O 流
⭐⭐⭐⭐
✅ 最终推荐:
CoroNet —— 简洁、明确、易拼写、域名可用(coronet.dev / .io),开发者一眼看懂用途。
二、架构设计思想(核心原则)
🎯 总目标:
“Write like sync, run like async — on any platform.”
(像写同步代码一样简单,像异步引擎一样高效——跨平台。)
1. 分层架构(Layered Design)
1 2 3 4 5 6 7 8 9 10 11 ┌──────────────────────────────┐ │ User Application │ ← C++20 协程:co_await socket.recv() ├──────────────────────────────┤ │ CoroNet Runtime (Core) │ ← 协程调度器 + 跨平台抽象层 ├──────────────────────────────┤ │ Platform Backend │ │ ┌─────────────┬──────────┐ │ │ │ Linux │ Windows │ │ │ │ io_uring │ IOCP │ │ │ └─────────────┴──────────┘ │ └──────────────────────────────┘
各层职责:
层级
职责
用户层
编写 co_await connect(), co_await send(), co_await recv(),无回调、无状态机
Runtime Core
- 协程调度器(支持 work-stealing) - 统一 Awaitable 接口 - 超时、取消、错误传播机制
Platform Backend
- Linux: 封装 io_uring 提交/完成 - Windows: 封装 WSARecv/WSASend + IOCP 完成队列 - 自动选择最优后端
2. 关键设计原则
✅ 原则 1:零抽象惩罚(Zero-overhead Abstraction)
在各自平台使用原生最优 I/O 机制 (io_uring / IOCP),不降级到 epoll 或 select。
编译期多态(via #ifdef _WIN32 或 traits),避免运行时虚函数开销。
✅ 原则 2:统一 Awaitable 接口
1 2 3 auto data = co_await socket.recv (1024 );co_await socket.send (buffer);
底层 recv() 返回一个 Awaitable<T> 对象,在 co_await 时挂起协程,并注册到平台后端。
完成时由后端唤醒协程并返回结果。
✅ 原则 3:协程调度与 I/O 解耦
调度器(Scheduler)管理所有协程生命周期。
I/O 后端只负责“通知完成”,不直接操作协程栈。
支持:- 单线程调度(客户端场景)
✅ 原则 4:资源安全与 RAII
socket、buffer、timer 等均支持 RAII。
协程取消时自动清理 pending I/O(io_uring 可 cancel,IOCP 可关闭 socket 触发 ERROR_OPERATION_ABORTED)。
✅ 原则 5:可观察性与调试友好
内置 trace ID、协程上下文日志。
支持 hook 到 Prometheus / OpenTelemetry(可选)。
3. 核心组件设计
组件
说明
coronet::TcpSocket
封装平台 socket,提供 connect, send, recv 等 awaitable 方法
coronet::IoContext
I/O 上下文,管理 io_uring ring 或 IOCP completion port
coronet::Scheduler
协程调度器,支持 spawn() 启动新协程
coronet::Timer
高精度定时器(io_uring timeout / Windows waitable timer)
coronet::BufferPool
零拷贝缓冲池,避免频繁内存分配
4. 跨平台实现策略
功能
Linux实现
Windows实现
异步 recv
io_uring_prep_recv
WSARecv + OVERLAPPED
异步 send
io_uring_prep_send
WSASend + OVERLAPPED
事件循环
io_uring_wait_cqe
GetQueuedCompletionStatusEx
定时器
io_uring_prep_timeout
CreateThreadpoolTimer 或 SetWaitableTimer
错误码
errno / -ret
WSAGetLastError()
🔧 使用 CMake + feature test 自动启用 io_uring(需 liburing >= 2.0)或 fallback 到 epoll(兼容旧内核)。
三、示例代码(愿景)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <coronet/coronet.hpp> coronet::Task<void > echo_client (std::string host, uint16_t port) { coronet::TcpSocket sock; co_await sock.connect (host, port); std::string msg = "Hello, CoroNet!" ; co_await sock.send (msg); auto reply = co_await sock.recv (1024 ); std::cout << "Reply: " << reply << "\n" ; } int main () { coronet::IoContext ctx; ctx.spawn (echo_client ("127.0.0.1" , 8888 )); ctx.run (); }
四、项目定位与差异化
对比项
Boost.Asio
Seastar
CoroNet(你的项目)
协程支持
C++20(实验性)
自研 fiber
原生 C++20 协程优先
Linux 后端
epoll
aio + dpdk
io_uring(最新)
Windows 后端
IOCP
❌ 不支持
IOCP(深度优化)
跨平台
✅
❌(Linux only)
✅
学习曲线
中高
高
低(同步风格)
💡 CoroNet 的核心价值 :
在 Windows 和 Linux 上,都提供接近硬件极限的性能,同时让用户写出最简单的代码。
五、下一步建议
命名确认 :注册 coronet GitHub 仓库(如 github.com/yourname/coronet)
MVP 路线图 :- 实现 Linux io_uring TCP recv/send
实现 Windows IOCP TCP recv/send
封装统一 Awaitable 接口
添加协程调度器
跨平台 CMake 构建
参考项目 :- folly::AsyncSocket
如果你决定启动这个项目,CoroNet 将填补 C++ 生态中“现代化、跨平台、协程优先、极致性能”网络库的空白 。这不仅是技术挑战,更是对 C++ 系统编程未来的一次推动。
CoroNet 协成完整的状态机转换
让我详细展示从创建到销毁的完整生命周期
1 2 3 4 5 6 7 8 9 10 task<int > make_task () { co_return 42 ; } task<void > caller () { auto t = make_task (); int result = co_await t; }
阶段 1:Task 创建(未开始)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 make_task() 被调用 ↓ 创建 task_promise<int> ↓ 调用 initial_suspend() → suspend_always ↓ 返回 task<int> 对象(包含 coroutine_handle) ↓ 此时协程处于:"初始挂起"状态 ┌──────────────────────┐ │ task_promise │ │ ├─ state: mono │ │ ├─ value: 未初始化 │ │ └─ parent_coro: │ │ noop_coroutine() │ └──────────────────────┘
阶段 2:第一次 co_await t
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 执行 co_await t (t 是左值) ↓ 调用 t.operator co_await() const & ↓ 创建 awaiter 对象 ┌──────────────────────┐ │ awaiter │ │ ├─ awaiter_base │ │ │ └─ handle ───────┼──→ task_promise │ └─ (无额外成员) │ └──────────────────────┘ ↓ 编译器执行 await_ready() ↓ 检查:!handle || handle.done() ↓ 返回 false (协程未完成) ↓ 【需要挂起 caller 协程】
阶段 3:await_suspend 建立父子关系
1 2 3 4 5 6 7 8 9 10 11 await_suspend (caller_handle) { handle.promise ().set_parent (caller_handle); return handle; }
此时的栈帧关系:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ┌─────────────────┐ │ caller 协程 │ ← 被挂起 │ ├─ state: │ │ │ waiting │ │ └─ resume_point:│ │ after co_await│ └─────────────────┘ ↑ │ parent_coro │ ┌─────────────────┐ │ task 协程 │ ← 正在执行 │ ├─ state: │ │ │ running │ │ └─ promise: │ │ parent_coro = │ │ caller_handle │ └─────────────────┘
阶段 4:Task 执行完毕
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 task 协程执行: co_return 42; ↓ 调用 promise.return_value(42) ↓ std::construct_at(&value, 42); state = value_state::value; ↓ ┌──────────────────────┐ │ task_promise │ │ ├─ state: value ✅ │ │ ├─ value: 42 │ │ └─ parent_coro ──────┼──→ caller_handle └──────────────────────┘ ↓ 调用 final_suspend() ↓ 返回 task_final_awaiter
阶段 5:final_suspend 返回父协程
1 2 3 4 5 6 7 8 template <typename T>struct task_final_awaiter { std::coroutine_handle<> await_suspend (std::coroutine_handle<Promise> current) noexcept { return current.promise ().parent_coro; } };
控制权转移:
1 2 3 4 5 6 7 8 9 10 task_final_awaiter.await_suspend() ↓ 读取 parent_coro (caller_handle) ↓ 返回 caller_handle ↓ 调度器恢复到 caller 协程 ↓ caller 从 co_await 处恢复执行
阶段 6:await_resume 获取结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 decltype (auto ) await_resume () { assert (this ->handle && "broken_promise" ); return this ->handle.promise ().result (); } T &result () & { if (state == value_state::exception) [[unlikely]] { std::rethrow_exception (exception_ptr); } assert (state == value_state::value); return value; }
最终结果:
1 2 3 4 int result = co_await t;
CoroNet 协成异常机制
异常产生流程:
1 2 3 4 5 task<int > may_throw () { throw std::runtime_error ("error" ); co_return 0 ; }
步骤分解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 1. 协程执行到 throw ↓ 2. 运行时捕获未处理异常 ↓ 3. 调用 promise.unhandled_exception() ↓ void unhandled_exception() noexcept { exception_ptr = std::current_exception(); state = value_state::exception; } ↓ 4. 继续执行 final_suspend ↓ 5. 返回父协程 ↓ 6. await_resume() 被调用 ↓ 7. result() 检查 state ↓ 8. std::rethrow_exception(exception_ptr) ↓ 9. 异常传播到 caller
io_context 架构图:
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 graph TD A[io_context] --> B[worker_meta] B --> C[io_uring Ring] B --> D[reap_swap 任务交换区] B --> E[SPSC Cursor] F[host_thread] --> A G[task<void> 协程] --> H[co_spawn] H --> I[worker_meta::co_spawn_auto] I --> J{是否跨线程?} J -->|否 | K[co_spawn_unsafe 本地提交] J -->|是 | L[msg_ring/eventfd 远程提交] K --> D L --> D M[调度循环] --> N[do_worker_part 执行协程] M --> O[do_submission_part 提交 IO] M --> P[do_completion_part 处理完成] N --> Q[从 reap_swap 取出协程] Q --> R[resume 协程] R --> S[协程发起 IO 请求] S --> T[SQE 提交到 io_uring] P --> U[CQE 从 io_uring 完成] U --> V[恢复对应协程] V --> D