# JingNet **Repository Path**: cjcj0213/jingnet ## Basic Information - **Project Name**: JingNet - **Description**: 高效高性能 适用于处理高并发事件 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-15 - **Last Updated**: 2026-05-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # JingNet - 高性能C++网络库 ## 项目概述 **JingNet** 是一个基于现代C++(C++17/20)开发的高性能网络库,采用主从Reactor架构设计,集成了协程调度、内存池、数据库连接池等企业级特性。项目参考了Muduo、Nginx等知名网络库的设计思想,旨在提供高并发、低延迟的网络服务解决方案。 ## 技术栈 - **语言标准**: C++17/20 - **操作系统**: Linux (epoll) - **核心特性**: 主从Reactor、协程、内存池、线程池 - **数据库**: MySQL (连接池)、Redis (缓存) - **日志**: spdlog - **构建**: Makefile/CMake --- ## 项目结构 ``` jingnet/ ├── include/ # 头文件目录 │ ├── tcpserver.h # TCP服务器主类(主从Reactor) │ ├── WorkerThread.h # 工作线程(从Reactor) │ ├── Channel.h # 事件通道封装 │ ├── EventLoop.h # 事件循环 │ ├── Epoller.h # epoll封装 │ ├── CoroutineScheduler.h # 协程调度器 │ ├── CoroutineTask.h # 协程任务 │ ├── Buffer.h # 环形缓冲区(解决粘包) │ ├── RedisClient.h # Redis客户端 │ ├── DatabaseManager.h # MySQL连接池管理器 │ ├── jsontype.h # JSON数据类型 │ ├── socket_traits.h # Socket特性模板 │ └── spdlog/ # 日志库 ├── src/ # 源码实现 │ ├── Channel.cpp │ ├── EventLoop.cpp │ ├── Epoller.cpp │ └── DatabaseManager.cpp ├── util/ # 工具类 │ ├── MemoryPool.h/cpp # 内存池 │ ├── ThreadCache.h/cpp # 线程本地缓存 │ ├── CentralCache.h/cpp # 中心缓存 │ ├── PageHeap.h/cpp # 页堆管理 │ ├── SizeMap.h # 大小映射表 │ ├── ThreadPoll.h # 线程池 │ ├── ipadd.h # IP地址封装 │ └── concurrentqueue.h # 无锁队列(moodycamel) ├── main.cpp # 程序入口 ├── test/ # 测试代码 ├── benchmark/ # 性能测试 └── 1.md # 项目文档(本文件) ``` --- ## 核心架构设计 ### 1. 主从Reactor架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ 主线程 (Main Thread) │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 主Reactor (Main Reactor) │ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ │ │ EventLoop │◄──►│ Epoller │ │ │ │ │ │ │ │ (epoll_wait)│ │ │ │ │ └─────────────┘ └──────┬──────┘ │ │ │ │ │ │ │ │ │ ┌──────▼──────┐ │ │ │ │ │AcceptChannel│ ◄── 只处理accept │ │ │ │ │(监听socket) │ │ │ │ │ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ │ │ 通过pipe分发 │ │ ▼ │ ├─────────────────────────────────────────────────────────────┤ │ 工作线程池 (4个线程) │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ Worker 0 │ │ Worker 1 │ ... │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ │ │ 从Reactor │ │ │ │ 从Reactor │ │ │ │ │ │ EventLoop │ │ │ │ EventLoop │ │ │ │ │ │ Epoller │ │ │ │ Epoller │ │ │ │ │ └──────┬──────┘ │ │ └──────┬──────┘ │ │ │ │ │ │ │ │ │ │ │ │ 客户端连接集合 │ │ 客户端连接集合 │ │ │ │ Channel[fd1] │ │ Channel[fd5] │ │ │ │ Channel[fd2] │ │ ... │ │ │ └─────────────────┘ └─────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` **设计要点**: - **主Reactor**: 只负责accept新连接,轻量高效 - **从Reactor**: 每个Worker线程一个,处理客户端IO - **无锁化**: 通过pipe传递fd,避免共享数据竞争 - **负载均衡**: 轮询算法将连接均匀分配给Worker ### 2. 内存池设计 (tcmalloc简化版) ``` ┌────────────────────────────────────────────┐ │ ThreadCache (TLS) │ ◄── 每个线程私有 │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 无锁分配 │ │ size 8 │ │ size 16 │ │ size 32 │ ... │ │ │ 链表 │ │ 链表 │ │ 链表 │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ └───────────┴───────────┘ │ │ │ │ │ 无内存时 ────────┼───────────────────────►│ │ ▼ │ ├────────────────────────────────────────────┤ │ CentralCache (全局) │ ◄── 需要锁 │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 批量分配 │ │ Span链表 │ │ Span链表 │ │ Span链表 │ ... │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ └───────────┴───────────┘ │ │ │ │ │ 无内存时 ────────┼───────────────────────►│ │ ▼ │ ├────────────────────────────────────────────┤ │ PageHeap (全局) │ ◄── 管理大块内存 │ ┌─────────────────────────────────────┐ │ │ │ Span管理 (1页 ~ 128页) │ │ │ │ 直接向OS申请/释放内存 │ │ │ └─────────────────────────────────────┘ │ └────────────────────────────────────────────┘ ``` **核心类**: - `MemoryPool`: 单例模式,统一分配接口 - `ThreadCache`: `thread_local`存储,每个线程独立的缓存 - `CentralCache`: 全局缓存,平衡各线程的内存使用 - `PageHeap`: 页堆管理,直接与操作系统交互 ### 3. 协程调度器 (C++20 Coroutine) ```cpp // 协程支持异步IO,代码写起来像同步 Task handleClient(int fd) { co_await async_read(fd, buffer); // 非阻塞等待读 process(buffer); co_await async_write(fd, response); // 非阻塞等待写 } ``` **特性**: - 基于C++20 `std::coroutine` - 集成epoll实现异步IO等待 - 支持定时协程调度 - 与线程池协作执行 ### 4. TCP粘包解决方案 **协议格式**: `[4字节长度前缀][N字节消息体]` ```cpp class RingBuffer { // 环形缓冲区设计 // 1. 接收数据直接append到缓冲区 // 2. tryGetMessage()解析长度前缀 // 3. 数据不够时返回false,等待下次读取 bool tryGetMessage(std::string& out) { if (size_ < sizeof(uint32_t)) return false; // 长度字段不够 uint32_t msgLen = peekUint32(); // 读取长度 if (size_ < sizeof(uint32_t) + msgLen) return false; // 数据不够 // 读取完整消息... } }; ``` --- ## 核心组件详解 ### TcpServer - 服务器主类 ```cpp namespace jingnet { template class TcpServer { public: TcpServer(int port, const std::string& ip); void start(); // 启动监听 void loop(); // 进入事件循环 private: void handleAccept(); // 接受新连接 void initWorkers(); // 初始化Worker线程 int m_socketFd; std::unique_ptr m_eventLoop; std::vector> m_workers; std::shared_ptr m_threadPool; std::shared_ptr m_coroutineScheduler; }; } // namespace jingnet ``` **配置选项** (SocketTraits): - `TCP_NODELAY`: 禁用Nagle算法,降低延迟 - `SO_REUSEADDR`: 地址复用 - `SO_REUSEPORT`: 端口复用,支持多进程负载均衡 ### WorkerThread - 工作线程 ```cpp class WorkerThread { public: WorkerThread(int pipefd, size_t id, ...); void start(); // 启动线程 void stop(); // 停止线程 private: void loop(); // 主循环 void handlePipeRead(); // 处理主线程通知 void handleNewClient(int fd); // 处理新连接 void handleClientRead(int fd); // 处理客户端数据 void checkTimeouts(); // 检查超时连接 int m_pipefd; // 与主线程通信的管道 std::unique_ptr m_eventLoop; std::unordered_map> m_clientChannels; std::priority_queue m_timeoutHeap; // 超时管理 }; ``` ### Channel - 事件通道 封装文件描述符和事件回调: ```cpp class Channel { public: void enableRead(); // 启用读事件 void enableWrite(); // 启用写事件 void enableET(); // 启用边缘触发 void handleEvent(); // 处理事件 void setReadCallback(EventCallback cb); void setWriteCallback(EventCallback cb); private: int fd_; // 文件描述符 uint32_t events_; // 关注的事件 uint32_t revents_; // 发生的事件 EventCallback readCb_, writeCb_, errorCb_; }; ``` ### 数据库支持 **MySQL连接池**: ```cpp // 配置数据库 DBConfig config; config.host = "127.0.0.1"; config.port = 3306; config.poolSize = 5; // 5个连接 // 初始化 DB_MANAGER.initialize(config); // 自动管理连接生命周期 auto conn = DB_MANAGER.acquireConnection(); conn->executeInsert("INSERT INTO ..."); // conn析构时自动归还连接池 ``` **Redis客户端** (单例模式): ```cpp RedisClient::instance().connect("127.0.0.1", 6379); RedisClient::instance().deviceOnline(deviceId, fd); RedisClient::instance().heartbeat(deviceId); // 续期 ``` --- ## 关键特性实现 ### 1. 心跳与超时管理 每个Worker线程维护一个小根堆管理连接超时: ```cpp struct TimeoutEntry { std::chrono::steady_clock::time_point deadline; int fd; int timeoutCount; // 超时次数,超过阈值关闭连接 bool operator>(const TimeoutEntry& other) const { return deadline > other.deadline; } }; // epoll_wait超时时间动态计算 int calculateTimeoutMs() { if (m_timeoutHeap.empty()) return 10000; // 默认10秒 auto& top = m_timeoutHeap.top(); if (top.deadline <= now) return 0; // 已超时,立即返回 return duration_cast(top.deadline - now).count(); } ``` ### 2. 线程池设计 基于moodycamel的无锁队列: ```cpp class ThreadPool { public: // 无返回值任务 template void enqueue(Func&& f); // 有返回值任务 template auto submit(Func&& f, Args&&... args) -> std::future<...>; private: moodycamel::ConcurrentQueue m_taskQueue; // 无锁队列 std::vector m_workers; }; ``` ### 3. 日志系统 集成spdlog,多sink输出: ```cpp void initLogger() { std::vector sinks; sinks.push_back(std::make_shared("log/server.log")); sinks.push_back(std::make_shared()); m_logger = std::make_shared("server", sinks.begin(), sinks.end()); m_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v"); } ``` --- ## 使用示例 ### 基础服务器 ```cpp #include "tcpserver.h" int main() { try { // 创建服务器,监听8080端口 jingnet::TcpServer<> server(8080, "0.0.0.0"); // 启动服务器 server.start(); // 进入事件循环 server.loop(); } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } return 0; } ``` ### 带数据库和Redis ```cpp int main() { // 初始化MySQL DBConfig dbConfig; dbConfig.host = "127.0.0.1"; dbConfig.port = 3306; dbConfig.username = "user"; dbConfig.password = "password"; dbConfig.database = "test_db"; dbConfig.poolSize = 5; DB_MANAGER.initialize(dbConfig); // 初始化Redis RedisClient::instance().connect("127.0.0.1", 6379); // 启动服务器 jingnet::TcpServer<> server(8080, "0.0.0.0"); server.start(); server.loop(); return 0; } ``` --- ## 性能优化点 | 优化点 | 实现方式 | 效果 | |--------|---------|------| | **无锁化** | 主从Reactor通过pipe通信,避免共享数据 | 减少锁竞争 | | **内存池** | thread_local缓存 + 批量分配 | 减少系统调用,降低碎片 | | **epoll ET模式** | 边缘触发 + 非阻塞IO | 减少epoll唤醒次数 | | **零拷贝** | 环形缓冲区直接操作 | 减少数据拷贝 | | **对象池** | Channel等对象复用 | 减少内存分配 | | **协程** | C++20协程避免回调地狱 | 提升开发效率,降低上下文切换 | --- ## 扩展建议 1. **添加TcpClient**: 实现客户端功能,支持连接池 2. **支持UDP**: 添加UDPServer类 3. **HTTP/WebSocket**: 基于TcpServer实现应用层协议 4. **SSL/TLS**: 集成OpenSSL支持加密传输 5. **配置热加载**: 支持运行时修改配置 6. **监控指标**: 集成prometheus,暴露QPS、延迟等指标 --- ## 参考资源 - **Muduo**: 陈硕的高性能网络库 - **Nginx**: 事件驱动架构参考 - **tcmalloc**: Google内存分配器 - **libco**: 腾讯协程库 - **C++ Coroutines**: C++20协程标准 --- ## 作者信息 - **姓名**: 陈憬 - **联系方式**: 17520283327 - **项目**: JingNet - 高性能C++网络库 - **特点**: 代码注释详尽,适合学习网络编程和C++现代特性 --- *本文档由AI助手基于项目源码自动生成,描述了JingNet项目的整体架构和核心实现。*