cnetmod基于 C23 模块和原生协程的跨平台异步网络库。https://github.com/banderzhm/cnetmod平台支持平台I/O 引擎编译器状态WindowsIOCPMSVC 2022 17.12✅Linuxio_uring epollclang-21 libc✅macOSkqueueclang-21 libc✅功能特性核心运行时协程引擎:taskT、spawn()即发即弃、对称传输实现尾调用优化I/O 上下文: 平台原生事件循环IOCP / io_uring / epoll / kqueue 线程安全的post()多核支持:server_context包含专用接受线程 N 个工作io_context线程 stdexec 线程池stdexec 集成:schedule()sender、async_scope、blocking_invoke()用于卸载阻塞调用网络功能TCP: 异步 accept / connect / read / write带 RAII socket 封装UDP: 异步 sendto / recvfromTLS/SSL: 基于 OpenSSL 的ssl_context/ssl_stream支持异步握手、SNI、客户端证书异步 DNS:async_resolve()— 通过 stdexec 线程池 getaddrinfo实现非阻塞 DNS串口: 跨平台异步串口 I/O协议支持HTTP/1.1 HTTP/2: 完整服务器包含路由器、中间件管道、分块传输、多部分上传HTTP/2 通过 TLS ALPN 协商支持多路复用流WebSocket: 服务端从 HTTP 升级、帧编解码、ping/pong、per-message deflateMQTT v3.1.1 / v5.0: 完整 broker 异步客户端 — QoS 0/1/2、保留消息、遗嘱、会话恢复、共享订阅、主题别名、自动重连同步客户端封装MySQL: 异步客户端支持预处理语句、连接池、管道、事务管理、ORMCRUD / 迁移 / 查询构建器 / MyBatis-Plus 风格 XML 映射器 / BaseMapper / 分页 / 软删除 / 乐观锁 / 多租户 / 缓存Redis: 异步客户端支持 RESP 协议、连接池Modbus: 完整协议实现 — TCP/UDP/RTU串口客户端和服务端、所有标准功能码、连接池、CRC-16 校验、帧时序控制、数据存储基于互斥锁和无锁通道OpenAI: 异步 API 客户端聊天补全等中间件HTTPCORS、JWT 认证、速率限制、gzip 压缩、请求体大小限制、请求 ID、访问日志、指标、超时、优雅关闭、IP 防火墙、缓存、健康检查、文件上传、panic 恢复同步原语mutex、shared_mutex、semaphore、condition_variable均支持协程、channelT、wait_group、cancel_token实用工具定时器:async_sleep()、async_sleep_until()、with_timeout()用于可取消操作缓冲区: 字节序感知的读写器、缓冲池日志: 基于std::format的日志器无外部依赖崩溃转储: 平台原生 minidumpWindows/ 信号处理器Unix异步文件 I/O: 基于 IOCPWindows快速开始构建要求CMake 4.0是 C23 模块支持所必需的。Windows: Visual Studio 2022 17.12 并启用 C23 模块。Linux: clang-21 libc liburing-dev。wgethttps://apt.llvm.org/llvm.shchmodx llvm.shsudo./llvm.sh21allsudoaptinstalllibc-21-dev libcabi-21-dev liburing-devmacOS: Homebrew LLVM 21系统 clang 不支持 C23 模块。brewinstallllvm ninja cmakeexportPATH/opt/homebrew/opt/llvm/bin:$PATH# Apple SiliconexportPATH/usr/local/opt/llvm/bin:$PATH# Intel Mac克隆和构建# 克隆仓库gitclone https://github.com/banderzhm/cnetmod.gitcdcnetmod# 初始化子模块第三方依赖所必需gitsubmodule update--init--recursive# 构建cmake-Bbuild-DCNETMOD_BUILD_EXAMPLESON cmake--buildbuild构建系统会自动检测 MSVC 和 libc 的标准库模块路径。如果检测失败手动指定# Linux/macOS with clangcmake-Bbuild\-DLIBCXX_MODULE_DIRS/usr/lib/llvm-21/share/libc/v1\-DLIBCXX_INCLUDE_DIRS/usr/lib/llvm-21/include/c/v1# Windows MSVCcmake-Bbuild\-DLIBCXX_MODULE_DIRSC:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.44.35207/modules示例Echo 服务器TCP 协程importcnetmod;usingnamespacecnetmod;taskvoidhandle_client(tcp_socket client){charbuf[1024];while(true){intnco_awaitclient.async_recv(buf,sizeof(buf));if(n0)break;co_awaitclient.async_send(buf,n);}}taskvoidserver(io_contextctx){tcp_acceptoracceptor(ctx,8080);while(true){auto[client,addr]co_awaitacceptor.async_accept();spawn(ctx,handle_client(std::move(client)));}}intmain(){net_init guard;// Windows 上的 WSAStartup RAIIio_context ctx;spawn(ctx,server(ctx));ctx.run();}MQTT Broker 客户端importcnetmod.protocol.mqtt;// 启动 brokermqtt::brokerbrk(ctx);brk.set_options({.port1883});brk.listen();spawn(ctx,brk.run());// 异步客户端mqtt::clientcli(ctx);co_awaitcli.connect({.host127.0.0.1,.port1883,.versionmqtt::protocol_version::v5});co_awaitcli.subscribe(sensor/#,mqtt::qos::at_least_once);cli.on_message([](constmqtt::publish_messagemsg){std::println(topic{} payload{},msg.topic,msg.payload);});co_awaitcli.publish(sensor/temp,22.5,mqtt::qos::exactly_once);co_awaitcli.disconnect();Modbus 协议importcnetmod.protocol.modbus;// TCP 客户端modbus::tcp_clientclient(ctx);co_awaitclient.connect(192.168.1.100,502);autoreqmodbus::request_builder().unit_id(1).read_holding_registers(0,10).build();autorespco_awaitclient.execute(req);// RTU 服务端串口modbus::memory_data_store store;modbus::rtu_server_config config;config.port_nameCOM3;// Windows 或 /dev/ttyUSB0 (Linux)config.baudrate9600;config.unit_id1;modbus::rtu_serverserver(ctx,store);co_awaitserver.start(config);定时器taskvoiddelayed_task(io_contextctx){co_awaitasync_sleep(ctx,1s);std::cout1 秒已过\n;}Channel生产者-消费者channelintch(10);spawn(ctx,producer(ch));// 发送 0..9spawn(ctx,consumer(ch));// 接收并打印taskvoidproducer(channelintch){for(inti0;i10;i)co_awaitch.send(i);ch.close();}MySQL ORM模型映射 CRUD 迁移 高级特性importcnetmod.protocol.mysql;#includecnetmod/orm.hpp// 定义带高级特性的模型structUser{std::int64_tid0;std::string name;std::optionalstd::stringemail;std::int32_tversion0;// 乐观锁std::int32_tdeleted0;// 软删除std::time_t created_at0;// 插入时自动填充std::time_t updated_at0;// 插入/更新时自动填充};CNETMOD_MODEL(User,users,CNETMOD_FIELD(id,id,bigint,PK|AUTO_INC),CNETMOD_FIELD(name,name,varchar),CNETMOD_FIELD(email,email,varchar,NULLABLE),CNETMOD_FIELD(version,version,int_,VERSION),CNETMOD_FIELD(deleted,deleted,tinyint,LOGIC_DELETE),CNETMOD_FIELD(created_at,created_at,timestamp,FILL_INSERT),CNETMOD_FIELD(updated_at,updated_at,timestamp,FILL_INSERT_UPDATE))taskvoiddemo(mysql::clientcli){orm::db_sessiondb(cli);// DDL — create / drop / sync_schema自动迁移co_awaitdb.create_tableUser();co_awaitorm::sync_schemaUser(cli);// 检测差异并应用 ALTER TABLE// INSERT自增 ID 自动填充User u;u.nameAlice;u.emailab.com;co_awaitdb.insert(u);// u.id 现在已设置co_awaitdb.insert_many(batch);// 批量插入// SELECT — find_all / find_by_id / 查询构建器autoallco_awaitdb.find_allUser();autooneco_awaitdb.find_by_idUser(param_value::from_int(1));autotopco_awaitdb.find(orm::selectUser().where(name {},{param_value::from_string(Alice)}).order_by(id DESC).limit(10).offset(0));// UPDATE — 按主键u.nameBob;co_awaitdb.update(u);// DELETE — 按模型 / 按 ID / 条件删除co_awaitdb.remove(u);co_awaitdb.remove_by_idUser(param_value::from_int(1));co_awaitdb.remove(orm::delete_ofUser().where(name {},{param_value::from_string(test)}));}// BaseMapper — 通用 CRUD 接口taskvoidbase_mapper_demo(mysql::clientcli){base_mapperUsermapper(cli);// QueryWrapper — 流式查询构建器query_wrapperUserwrapper;wrapper.eq(status,1).like(name,%Alice%).gt(age,18).order_by_desc(created_at).limit(10);autousersco_awaitmapper.select_list(wrapper);// 分页autopageco_awaitmapper.select_page(1,10,wrapper);std::println(第 {}/{} 页总数: {},page.current_page,page.total_pages,page.total);}// MyBatis-Plus 风格 XML 映射器 — 动态 SQLtaskvoidxml_mapper_demo(mysql::clientcli){mapper_registry registry;registry.load_file(mappers/user_mapper.xml);mapper_sessionsession(cli,registry);// 执行带动态条件的查询autoresultco_awaitsession.queryUser(UserMapper.findByCondition,param_context::from_map({{name,param_value::from_string(Alice)},{status,param_value::from_int(1)}}));}ID 策略 — 内置 UUID v4 和 SnowflakestructTag{orm::uuid id;std::string name;};CNETMOD_MODEL(Tag,tags,CNETMOD_FIELD(id,id,char_,UUID_PK_FLAGS,UUID_PK_STRATEGY),CNETMOD_FIELD(name,name,varchar))structEvent{std::int64_tid0;std::string title;};CNETMOD_MODEL(Event,events,CNETMOD_FIELD(id,id,bigint,SNOWFLAKE_PK_FLAGS,SNOWFLAKE_PK_STRATEGY),CNETMOD_FIELD(title,title,varchar))// Snowflake 需要生成器orm::snowflake_generatorsf(/*machine_id*/1);orm::db_sessiondb(cli,sf);co_awaitdb.insert(event);// event.id 自动生成查看examples/获取完整示例包括http_demo、http2_demo、ws_demo、mqtt_demo、mysql_crud、mysql_orm、redis_client、modbus_demo、multicore_http、ssl_echo_server等。架构模块结构: 纯 C23 模块接口.cppm无头文件。平台特定实现在.cpp文件中通过 CMake 选择。cnetmod.core — socket、buffer、address、error、log、dns、ssl、serial_port cnetmod.coro — task、spawn、channel、mutex、semaphore、timer、cancel cnetmod.io — io_context 平台后端iocp、io_uring、epoll、kqueue cnetmod.executor — async_op、server_context、scheduler、stdexec 桥接 cnetmod.protocol.tcp — TCP acceptor/connector cnetmod.protocol.udp — UDP 异步 I/O cnetmod.protocol.http — HTTP/1.1 HTTP/2 服务器、路由器、中间件管道、ALPN 协商 cnetmod.protocol.websocket — WebSocket 服务器 cnetmod.protocol.mqtt — MQTT broker 客户端v3.1.1 / v5.0 cnetmod.protocol.mysql — MySQL 异步客户端 ORM cnetmod.protocol.redis — Redis 异步客户端 cnetmod.protocol.modbus — Modbus TCP/UDP/RTU 客户端 服务端 cnetmod.protocol.openai — OpenAI API 客户端 cnetmod.middleware.* — HTTP 中间件组件调度器/执行器:io_context提供post(coroutine_handle)用于线程安全的任务提交。平台特定的wake()实现Windows:PostQueuedCompletionStatus 哨兵键Linux: 非阻塞管道 io_uring 读取macOS/epoll: eventfd/pipe 排空触发协程原语:taskT使用对称传输实现尾调用优化。spawn()通过detached_task将急切协程桥接到调度器。异步操作: 基于 RAII 的 async_op 基类带平台特定的 overlap/submission 跟踪。完成回调通过post()恢复等待的协程。已知问题MSVC 错误 C1605: 对象文件大小超过 4 GB 限制在 Debug 模式下使用 MSVC 构建时编译器可能报错fatal error C1605: 编译器限制: 对象文件大小不能超过 4 GB这是MSVC 的已知 bug。Microsoft 已在开发者社区中承认此问题C1605: C23 Modules Exceed 4 GB Object File Limit。问题的原因是编译器在处理 C23 模块 大量模板实例化特别是std模块 std::format 协议编解码器时错误地生成了超大对象文件。MSVC 的 COFF 对象格式有 4 GB 硬限制。推荐的解决方案使用 Release/RelWithDebInfo 构建— 优化构建产生的对象文件要小得多可以避免此编译器 bug。在 WSL/Linux 上使用 clang 构建— clang libc 使用 ELF 对象没有 4 GB 限制。这是推荐的开发工作流。注意这是编译器的 bug不是 C23 模块或本库的限制。我们正在等待 Microsoft 修复此问题。详细分析请参见 MSVC_C1605_Issue.md。clang 模块依赖可见性在模块之间添加新的import依赖时clang 可能报错declaration of ‘X’ must be imported from module ‘Y’ before it is required确保显式导入导出所需符号的模块。与头文件不同模块具有严格的可见性 — 传递导入不会自动可见。设计理念为什么使用模块零成本的无头文件构建模型。减少编译时间更清晰的 API 表面。与 C23 标准库方向一致。为什么使用协程零开销的 async/await无回调地狱。无栈协程编译为状态机性能最优。为什么使用 io_uring/IOCP/kqueue平台原生异步 I/O 提供最佳性能。io_uring 避免系统调用开销。IOCP 是 Windows 服务器的久经考验的选择。kqueue 是 macOS 的唯一选项。为什么使用 stdexecsender/receiver 的事实标准。支持与其他异步库组合。通过async_scope实现结构化并发。用于阻塞操作卸载blocking_invoke。项目状态cnetmod 是一个展示 C23 模块和协程强大能力的现代网络库。它提供了 HTTP/1.1 HTTP/2、MQTT、MySQL、WebSocket、Modbus 等协议的生产级实现全部基于零开销的 async/await 构建。该库证明了 C23 模块已经可以用于实际项目并在 Linux、macOS 和 Windows 上提供完整的跨平台支持。许可证MIT 许可证。详见 LICENSE 文件。