├── .gitignore ├── README.md ├── common ├── base_lib │ ├── CCfg.cpp │ ├── CCfg.h │ ├── CCond.cpp │ ├── CCond.h │ ├── CLock.cpp │ ├── CLock.h │ ├── CLogger.cpp │ ├── CLogger.h │ ├── CMD5.cpp │ ├── CMD5.h │ ├── CMemManager.cpp │ ├── CMemManager.h │ ├── CMemMonitor.cpp │ ├── CMemMonitor.h │ ├── CMemPool.cpp │ ├── CMemPool.h │ ├── CMessageQueue.cpp │ ├── CMessageQueue.h │ ├── CMultiW_SingleR_Queue.cpp │ ├── CMultiW_SingleR_Queue.h │ ├── CMutex.cpp │ ├── CMutex.h │ ├── CProcess.cpp │ ├── CProcess.h │ ├── CRefObj.cpp │ ├── CRefObj.h │ ├── CShm.cpp │ ├── CShm.h │ ├── CSingleW_SingleR_Buffer.cpp │ ├── CSingleW_SingleR_Buffer.h │ ├── CThread.cpp │ ├── CThread.h │ ├── CTimer.cpp │ ├── CTimer.h │ ├── CUUId.cpp │ ├── CUUId.h │ ├── Constant.h │ ├── ErrorCode.h │ ├── Function.cpp │ ├── Function.h │ ├── MacroDefine.h │ ├── Makefile │ ├── Type.h │ ├── readme │ ├── xmlConfig.cpp │ └── xmlConfig.h ├── connect_lib │ ├── CClient.cpp │ ├── CClient.h │ ├── CConnectManager.cpp │ ├── CConnectManager.h │ ├── CDataHandler.cpp │ ├── CDataHandler.h │ ├── CDataTransmit.cpp │ ├── CDataTransmit.h │ ├── CEpoll.cpp │ ├── CEpoll.h │ ├── CSocket.cpp │ ├── CSocket.h │ ├── CTcpConnect.cpp │ ├── CTcpConnect.h │ ├── CUdp.cpp │ ├── CUdp.h │ ├── ILogicHandler.h │ ├── Makefile │ ├── NetType.h │ └── readme ├── db_lib │ ├── CMemcache.cpp │ ├── CMemcache.h │ ├── CMySql.cpp │ ├── CMySql.h │ ├── CRedis.cpp │ ├── CRedis.h │ ├── Makefile │ └── readme └── readme ├── frame ├── SrvFrame │ ├── CConnectMgr.cpp │ ├── CConnectMgr.h │ ├── CDataContent.cpp │ ├── CDataContent.h │ ├── CGameModule.cpp │ ├── CGameModule.h │ ├── CLogicHandler.cpp │ ├── CLogicHandler.h │ ├── CMakeLists.txt │ ├── CModule.cpp │ ├── CModule.h │ ├── CNetDataHandler.cpp │ ├── CNetDataHandler.h │ ├── CNetMsgComm.cpp │ ├── CNetMsgComm.h │ ├── CService.cpp │ ├── CService.h │ ├── FrameType.h │ ├── IService.h │ ├── UserType.h │ └── readme ├── SrvMsgComm │ ├── CMakeLists.txt │ ├── CNetMsgHandler.cpp │ ├── CNetMsgHandler.h │ ├── CSrvMsgComm.cpp │ ├── CSrvMsgComm.h │ └── readme ├── messageComm │ ├── CMakeLists.txt │ ├── CMsgComm.cpp │ ├── CMsgComm.h │ ├── ISrvMsgComm.h │ ├── Makefile │ ├── MsgCommType.h │ └── readme └── readme └── http_base ├── CHttpConnectMgr.cpp ├── CHttpConnectMgr.h ├── CHttpData.cpp ├── CHttpData.h ├── CHttpSrv.cpp ├── CHttpSrv.h ├── CMakeLists.txt └── HttpBaseDefine.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # game_service_system 2 | base lib, connect lib, db operator lib, develop frame, and game engine, game frame game service system! 3 | 从0开始开发 基础库(配置文件读写、日志、多线程、多进程、锁、对象引用计数、内存池、免锁消息队列、免锁数据缓冲区、进程信号、共享内存、定时器等等基础功能组件),网络库(socket、TCP、UDP、epoll机制、连接自动收发消息等等),数据库操作库(mysql,redis、memcache API 封装可直接调用),开发框架库(消息调度处理、自动连接管理、服务开发、游戏框架、服务间消息收发、消息通信等等),消息中间件服务(不同网络节点间自动传递收发消息)等多个功能组件、服务,最后完成一套完整的服务器引擎,基于该框架引擎可开发任意的网络服务。 主体架构:N网关+N服务+N数据库代理+内存DB(Redis、MemCache)+Mysql数据库,基于该架构可建立集群,稳定高效的处理大规模、高并发消息。 4 | -------------------------------------------------------------------------------- /common/base_lib/CCfg.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.27 4 | * description : 配置文件解析读取配置项 5 | */ 6 | 7 | #ifndef CCFG_H 8 | #define CCFG_H 9 | 10 | #include 11 | #include 12 | #include "Constant.h" 13 | #include "MacroDefine.h" 14 | #include "CProcess.h" 15 | 16 | 17 | typedef void (*ConfigUpdateNotify)(void* callBack); // 配置文件更新通知接口 18 | typedef std::unordered_map NotifyFuncToCB; 19 | 20 | namespace NCommon 21 | { 22 | 23 | struct Key2Value 24 | { 25 | char key[CfgKeyValueLen]; 26 | char value[CfgKeyValueLen]; 27 | Key2Value* pNext; 28 | 29 | Key2Value(const char* k, unsigned int kLen, const char* val, unsigned int vLen) : pNext(NULL) 30 | { 31 | if (kLen >= (unsigned int)CfgKeyValueLen) kLen = CfgKeyValueLen - 1; 32 | if (vLen >= (unsigned int)CfgKeyValueLen) vLen = CfgKeyValueLen - 1; 33 | 34 | memcpy(key, k, kLen); 35 | key[kLen] = '\0'; 36 | 37 | memcpy(value, val, vLen); 38 | value[vLen] = '\0'; 39 | } 40 | 41 | ~Key2Value() 42 | { 43 | key[0] = '\0'; 44 | value[0] = '\0'; 45 | pNext = NULL; 46 | } 47 | }; 48 | 49 | struct ConfigData; 50 | 51 | 52 | // 配置文件格式如下: 53 | /* 54 | 配置文件说明、注释信息等等 55 | [cfgSection1] 注意说明!配置文件的配置项必须在[section]下,否则配置格式错误 56 | key = value // 注释信息 57 | key1 = value 58 | ...... 59 | 60 | [cfgSection2] 61 | key = value 62 | ...... 63 | */ 64 | 65 | class CCfg 66 | { 67 | public: 68 | CCfg(const char* pCfgFile, const char* key2value[], const int len); 69 | ~CCfg(); 70 | 71 | public: 72 | static CCfg* initCfgFile(const char* pCfgFile, const char* key2value[], const int len); // 进程启动时先调用此函数初始化配置文件 73 | static CCfg* useDefaultCfg(const char* pCfgFile = NULL); // 使用系统默认的配置 74 | static CCfg* reLoadCfg(); // 重新加载更新配置项 75 | 76 | // 获取配置项值 77 | static const char* getValue(const char* section, const char* key); 78 | static const Key2Value* getValueList(const char* section); 79 | static const char* getKey(const char* section, const char* value); 80 | static const char* getKey(const char* section, const int value); 81 | 82 | public: 83 | const char* get(const char* section, const char* key); 84 | const Key2Value* getList(const char* section); 85 | const char* getKeyByValue(const char* section, const char* value); 86 | const char* getKeyByValue(const char* section, const int value); 87 | 88 | public: 89 | const char* getFileName() const; 90 | 91 | void reLoad(); 92 | 93 | public: 94 | static int createDir(const char* pCfgFile); 95 | 96 | private: 97 | int createFile(const char* pCfgFile, const char* key2value[], const int len); 98 | void createKV(const char* pCfgFile, bool isUpdate = false); 99 | void destroyKV(); 100 | void add(const char* key2value, bool isUpdate = false); 101 | const char* getItem(const char* section, const char* value, const bool isValue = true); 102 | 103 | ConfigData* getSectionData(const char* section); 104 | ConfigData* getCurCfgData(const char* data, bool& isSection); 105 | 106 | private: 107 | void output(); // only for test 108 | 109 | private: 110 | // 禁止拷贝、赋值 111 | CCfg(); 112 | CCfg(const CCfg&); 113 | CCfg& operator =(const CCfg&); 114 | 115 | private: 116 | ConfigData* m_cfgData; 117 | ConfigData* m_curCfgData; 118 | char m_fileName[MaxFullLen]; 119 | }; 120 | 121 | 122 | // 配置管理 123 | class CConfigManager 124 | { 125 | public: 126 | static void addUpdateNotify(ConfigUpdateNotify cfgUpdateNotify, void* callBack = NULL); 127 | static void removeUpdateNotify(ConfigUpdateNotify cfgUpdateNotify); 128 | 129 | private: 130 | static void notifyConfigUpdate(int sigNum, siginfo_t* sigInfo, void* context); 131 | 132 | private: 133 | static NotifyFuncToCB st_notifyFuncToCb; 134 | static bool st_isInit; 135 | 136 | DISABLE_CLASS_BASE_FUNC(CConfigManager); // 禁止实例化对象 137 | }; 138 | 139 | } 140 | 141 | #endif // CCFG_H 142 | -------------------------------------------------------------------------------- /common/base_lib/CCond.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.21 4 | * description : 线程同步通知API封装 5 | */ 6 | 7 | #include "CCond.h" 8 | #include "CMutex.h" 9 | #include "MacroDefine.h" 10 | 11 | 12 | namespace NCommon 13 | { 14 | 15 | CCond::CCond() 16 | { 17 | int rc = pthread_condattr_init(&m_condAttr); 18 | if (rc != 0) 19 | { 20 | ReleaseErrorLog("call pthread_condattr_init error = %d", rc); // 运行日志 21 | } 22 | 23 | rc = pthread_cond_init(&m_cond, &m_condAttr); 24 | if (rc != 0) 25 | { 26 | ReleaseErrorLog("call pthread_cond_init error = %d", rc); // 运行日志 27 | } 28 | } 29 | 30 | CCond::~CCond() 31 | { 32 | pthread_cond_destroy(&m_cond); 33 | pthread_condattr_destroy(&m_condAttr); 34 | } 35 | 36 | int CCond::wait(CMutex& mutex) 37 | { 38 | return pthread_cond_wait(&m_cond, mutex.get_mutex()); 39 | } 40 | 41 | int CCond::timedWait(CMutex& mutex, const struct timespec* time) 42 | { 43 | return pthread_cond_timedwait(&m_cond, mutex.get_mutex(), time); 44 | } 45 | 46 | int CCond::signal() 47 | { 48 | return pthread_cond_signal(&m_cond); 49 | } 50 | 51 | int CCond::broadCast() 52 | { 53 | return pthread_cond_broadcast(&m_cond); 54 | } 55 | 56 | } 57 | 58 | -------------------------------------------------------------------------------- /common/base_lib/CCond.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.21 4 | * description : 线程同步通知API封装 5 | */ 6 | 7 | #ifndef CCOND_H 8 | #define CCOND_H 9 | 10 | #include 11 | 12 | 13 | namespace NCommon 14 | { 15 | class CMutex; 16 | 17 | class CCond 18 | { 19 | public: 20 | CCond(); 21 | ~CCond(); 22 | 23 | public: 24 | int wait(CMutex& mutex); 25 | int timedWait(CMutex& mutex, const struct timespec* time); 26 | int signal(); 27 | int broadCast(); 28 | 29 | private: 30 | // 禁止拷贝、赋值 31 | CCond(const CCond&); 32 | CCond& operator =(const CCond&); 33 | 34 | private: 35 | pthread_condattr_t m_condAttr; // 为了支持以后好扩展使用 36 | pthread_cond_t m_cond; 37 | }; 38 | 39 | } 40 | 41 | #endif // CCOND_H 42 | 43 | 44 | -------------------------------------------------------------------------------- /common/base_lib/CLock.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.19 4 | * description : 自动加解锁调用,防止处理流程中异常抛出而导致无解锁动作死锁 5 | */ 6 | 7 | #include "CLock.h" 8 | #include "CMutex.h" 9 | 10 | namespace NCommon 11 | { 12 | 13 | CLock::CLock(CMutex& rMutex) : m_rMutex(rMutex) 14 | { 15 | Success = m_rMutex.lock(); 16 | } 17 | 18 | CLock::~CLock() 19 | { 20 | if (Success == 0) m_rMutex.unLock(); 21 | } 22 | 23 | 24 | CLockEx::CLockEx(std::mutex* pMutex) : m_success(-1), m_pMutex(pMutex) 25 | { 26 | lock(); 27 | } 28 | 29 | CLockEx::~CLockEx() 30 | { 31 | unlock(); 32 | } 33 | 34 | bool CLockEx::isLocked() const 35 | { 36 | return (m_success == 0); 37 | } 38 | 39 | void CLockEx::lock() 40 | { 41 | if (m_pMutex != NULL) 42 | { 43 | m_pMutex->lock(); 44 | m_success = 0; 45 | } 46 | } 47 | 48 | void CLockEx::unlock() 49 | { 50 | if (m_success == 0) 51 | { 52 | m_pMutex->unlock(); 53 | m_success = -1; 54 | } 55 | } 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /common/base_lib/CLock.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.19 4 | * description : 自动加解锁调用,防止处理流程中异常抛出而导致无解锁动作死锁 5 | */ 6 | 7 | #ifndef CLOCK_H 8 | #define CLOCK_H 9 | 10 | #include 11 | 12 | 13 | namespace NCommon 14 | { 15 | 16 | class CMutex; 17 | 18 | class CLock 19 | { 20 | public: 21 | CLock(CMutex& rMutex); 22 | int Success; 23 | 24 | ~CLock(); 25 | 26 | private: 27 | // 禁止拷贝、赋值 28 | CLock(); 29 | CLock(const CLock&); 30 | CLock& operator =(const CLock&); 31 | 32 | private: 33 | CMutex& m_rMutex; 34 | }; 35 | 36 | 37 | class CLockEx 38 | { 39 | public: 40 | CLockEx(std::mutex* pMutex); 41 | ~CLockEx(); 42 | 43 | bool isLocked() const; 44 | void lock(); 45 | void unlock(); 46 | 47 | private: 48 | // 禁止拷贝、赋值 49 | CLockEx(); 50 | CLockEx(const CLockEx&); 51 | CLockEx& operator =(const CLockEx&); 52 | 53 | private: 54 | int m_success; 55 | std::mutex* m_pMutex; 56 | }; 57 | 58 | } 59 | 60 | #endif // CLOCK_H 61 | -------------------------------------------------------------------------------- /common/base_lib/CLogger.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.28 4 | * description : 提供各种日志输出、日志管理功能 5 | */ 6 | 7 | #ifndef CLOGGER_H 8 | #define CLOGGER_H 9 | 10 | #include "Constant.h" 11 | 12 | 13 | struct tm; 14 | struct timeval; 15 | 16 | namespace NCommon 17 | { 18 | 19 | enum LogLevel { 20 | Info = 2, 21 | Warn = 3, 22 | Error = 4, 23 | Business = 5, 24 | Dev = 6, 25 | Test = 7, 26 | Product = 8, 27 | }; 28 | 29 | /* 调试日志 30 | 日志级别开关配置说明: 31 | enum LogLevel { 32 | Info = 2, 33 | Warn = 3, 34 | Error = 4, 35 | Business = 5, 36 | Dev = 6, 37 | Test = 7, 38 | Product = 8, 39 | }; 40 | 41 | 各服务配置文件 common.cfg 里的 [Logger] 配置项: 42 | [Logger] 43 | WriteDebugLog = 0 // 0值关闭日志 44 | WriteDebugLog = 1 // 1值打开所有级别的日志 45 | 46 | // 打开相关级别的日志,各级别对应的值 LogLevel 任意组合,如下配置: 47 | WriteDebugLog = 2 // 只打开 Info 级别日志 48 | WriteDebugLog = 45 // 只打开 Error、Business 级别日志 49 | WriteDebugLog = 34 // 只打开 Warn、Error 级别日志 50 | WriteDebugLog = 478 // 只打开 Error、Test、Product 级别日志 51 | */ 52 | 53 | 54 | class CLogger 55 | { 56 | public: 57 | CLogger(const char* pFullName, long size, int maxBakFile, int output = 1); 58 | ~CLogger(); 59 | 60 | public: 61 | static CLogger& getDebugLogger(); 62 | static CLogger& getReleaseLogger(); 63 | static CLogger& getOptLogger(); 64 | 65 | public: 66 | int writeFile(const char* fileName, const int fileLine, const LogLevel logLv, const char* pFormat, ...); 67 | void setOutput(int value); 68 | 69 | private: 70 | void setFileName(const char* pFullName); 71 | void setDirName(const char* pFullName); 72 | 73 | private: 74 | int formatHead(char* logBuff, const int len, const struct tm* pTm, const struct timeval& tv, const LogLevel logLv, 75 | const char* fileName, const int fileLine); 76 | bool createDir(); 77 | int openCurrentFile(); 78 | int openNextFile(int idx, char* fullName, unsigned int len); 79 | void reOpenFile(int wLen); 80 | void checkAndNewFile(int wLen); 81 | void closeFile(); 82 | bool checkCurrentFileIsExist(); 83 | 84 | private: 85 | // 禁止拷贝、赋值 86 | CLogger(); 87 | CLogger(const CLogger&); 88 | CLogger& operator =(const CLogger&); 89 | 90 | private: 91 | const char** m_pDir; // 目录名 92 | char* m_pName; // 文件名 93 | char m_fullName[MaxFullLen]; // 当前文件名 94 | int m_dirSize; // 目录级数 95 | long m_maxSize; // 文件最大长度,超过该长度将自动写新文件 96 | long m_curSize; // 文件当前长度 97 | int m_maxBakFile; // 最多保留的备份文件个数 98 | int m_idx; // 文件名后缀,从1开始 99 | int m_fd; // 文件描叙符句柄 100 | int m_output; // 是否输出日志,非0值输出,0值关闭 101 | 102 | private: 103 | // 保护机制 104 | int m_writeErrTimes; // 连续写多少次失败后,重新打开文件 105 | int m_tryTimes; // 连续尝试打开多少次文件失败后,关闭日志功能 106 | 107 | 108 | // only for do test,测试代码 109 | public: 110 | void output(); 111 | void testWriteFile(int n); 112 | }; 113 | 114 | 115 | } 116 | 117 | #endif // CLOGGER_H 118 | -------------------------------------------------------------------------------- /common/base_lib/CMD5.h: -------------------------------------------------------------------------------- 1 | #ifndef __MD5_H__ 2 | #define __MD5_H__ 3 | 4 | //#pragma warning(disable:4786) 5 | 6 | #include 7 | 8 | namespace NCommon 9 | { 10 | 11 | using namespace std; 12 | 13 | /*! 14 | * Manage MD5. 15 | */ 16 | class CMD5 17 | { 18 | public: 19 | struct md5_context 20 | { 21 | unsigned int total[2]; 22 | unsigned int state[4]; 23 | unsigned char buffer[64]; 24 | }; 25 | 26 | void md5_starts( struct md5_context *ctx ); 27 | void md5_process(struct md5_context *ctx, const unsigned char data[64]); 28 | void md5_update(struct md5_context *ctx, const unsigned char *input, unsigned int length); 29 | void md5_finish( struct md5_context *ctx, unsigned char digest[16] ); 30 | 31 | public: 32 | //! construct a CMD5 from any buffer 33 | void GenerateMD5(const unsigned char* buffer, unsigned int bufferlen); 34 | 35 | //! construct a CMD5 36 | CMD5(); 37 | 38 | //! construct a md5src from char * 39 | CMD5(const char * md5src); 40 | 41 | //! construct a CMD5 from a 16 bytes md5 42 | CMD5(unsigned long* md5src); 43 | 44 | //! add a other md5 45 | CMD5 operator +(CMD5 adder); 46 | 47 | //! just if equal 48 | bool operator ==(CMD5 cmper); 49 | 50 | //! give the value from equer 51 | // void operator =(CMD5 equer); 52 | 53 | //! to a string 54 | string ToString(); 55 | 56 | unsigned long m_data[4]; 57 | }; 58 | 59 | } 60 | #endif /* md5.h */ 61 | 62 | -------------------------------------------------------------------------------- /common/base_lib/CMemManager.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.16 4 | * description : 自动内存块内存池管理,快速高效的获取、释放内存,防止内存碎片 5 | */ 6 | 7 | #include "CMemManager.h" 8 | #include "CMemPool.h" 9 | #include "MacroDefine.h" 10 | 11 | 12 | namespace NCommon 13 | { 14 | 15 | static const int AddrSize = sizeof(CMemPool*); // 指针占用内存的长度 16 | 17 | struct MemPoolContainer 18 | { 19 | CMemPool memPool; 20 | MemPoolContainer* pNext; 21 | 22 | MemPoolContainer(const unsigned int count, const unsigned int size) : memPool(count, size), pNext(NULL) {} 23 | }; 24 | 25 | 26 | // 第一次分配count块长度为size的内存,用完则自动分配step块内存 27 | // 注意:count&step 的取值至少大于1,否则不会创建内存池 28 | CMemManager::CMemManager(const unsigned int count, const unsigned int step, const unsigned int size) : m_buffSize(size), m_step(0), m_pHeader(NULL) 29 | { 30 | if (count <= 1 || step <= 1 || size == 0) 31 | { 32 | return; 33 | } 34 | 35 | m_step = step; 36 | createPool(count, size + AddrSize, m_pHeader); 37 | } 38 | 39 | CMemManager::~CMemManager() 40 | { 41 | m_step = 0; 42 | clear(); 43 | } 44 | 45 | char* CMemManager::get() 46 | { 47 | char* pRet = NULL; 48 | 49 | MemPoolContainer* pPre = NULL; 50 | MemPoolContainer* pCur = m_pHeader; 51 | while (pCur != NULL) 52 | { 53 | pRet = pCur->memPool.get(); 54 | if (pRet != NULL) 55 | { 56 | pRet += AddrSize; // 用户buff块的起始地址 57 | if (pPre != NULL) 58 | { 59 | // 把非空内存池调整到链表头部 60 | pPre->pNext = pCur->pNext; 61 | pCur->pNext = m_pHeader; 62 | m_pHeader = pCur; 63 | } 64 | break; 65 | } 66 | 67 | pPre = pCur; 68 | pCur = pCur->pNext; 69 | } 70 | 71 | if (pRet == NULL && m_step > 1) // 内存池没内存块了,则创建新的内存池 72 | { 73 | MemPoolContainer* pMemPoolContainer = NULL; 74 | if (createPool(m_step, m_buffSize + AddrSize, pMemPoolContainer)) 75 | { 76 | pMemPoolContainer->pNext = m_pHeader; 77 | m_pHeader = pMemPoolContainer; 78 | pRet = pMemPoolContainer->memPool.get(); 79 | pRet += AddrSize; // 用户buff块的起始地址 80 | } 81 | } 82 | 83 | return pRet; 84 | } 85 | 86 | void CMemManager::put(char* p) 87 | { 88 | if (p != NULL) 89 | { 90 | p -= AddrSize; 91 | CMemPool* mp = (CMemPool*)(*(unsigned long*)p); 92 | mp->put(p); 93 | } 94 | } 95 | 96 | // 释放空闲的内存池 97 | void CMemManager::free() 98 | { 99 | MemPoolContainer* pDelete = NULL; 100 | MemPoolContainer* pPre = NULL; 101 | MemPoolContainer* pCur = m_pHeader; 102 | while (pCur != NULL) 103 | { 104 | if (pCur->memPool.full()) 105 | { 106 | pDelete = pCur; 107 | if (pPre != NULL) 108 | { 109 | pPre->pNext = pCur->pNext; 110 | } 111 | else 112 | { 113 | m_pHeader = pCur->pNext; 114 | } 115 | pCur = pCur->pNext; 116 | destroyPool(pDelete); 117 | continue; 118 | } 119 | 120 | pPre = pCur; 121 | pCur = pCur->pNext; 122 | } 123 | } 124 | 125 | // 释放所有内存池 126 | void CMemManager::clear() 127 | { 128 | MemPoolContainer* pDelete = NULL; 129 | MemPoolContainer* pCur = m_pHeader; 130 | m_pHeader = NULL; 131 | while (pCur != NULL) 132 | { 133 | pDelete = pCur; 134 | pCur = pCur->pNext; 135 | destroyPool(pDelete); 136 | } 137 | } 138 | 139 | unsigned int CMemManager::getBuffSize() const 140 | { 141 | return m_buffSize; 142 | } 143 | 144 | unsigned int CMemManager::getFreeCount() const 145 | { 146 | unsigned int count = 0; 147 | MemPoolContainer* pCur = m_pHeader; 148 | while (pCur != NULL) 149 | { 150 | count += pCur->memPool.getFreeCount(); 151 | pCur = pCur->pNext; 152 | } 153 | return count; 154 | } 155 | 156 | unsigned int CMemManager::getMaxCount() const 157 | { 158 | unsigned int count = 0; 159 | MemPoolContainer* pCur = m_pHeader; 160 | while (pCur != NULL) 161 | { 162 | count += pCur->memPool.getMaxCount(); 163 | pCur = pCur->pNext; 164 | } 165 | return count; 166 | } 167 | 168 | unsigned int CMemManager::getStep() const 169 | { 170 | return m_step; 171 | } 172 | 173 | // 注意:step 的取值至少大于1,否则不会创建内存池 174 | void CMemManager::setStep(unsigned int step) 175 | { 176 | if (step > 1) 177 | { 178 | m_step = step; 179 | } 180 | } 181 | 182 | bool CMemManager::createPool(const unsigned int count, const unsigned int size, MemPoolContainer*& pMemPoolContainer) 183 | { 184 | bool ok = false; 185 | NEW(pMemPoolContainer, MemPoolContainer(count, size)); 186 | if (pMemPoolContainer != NULL) 187 | { 188 | ok = pMemPoolContainer->memPool.init(&pMemPoolContainer->memPool); 189 | if (!ok) 190 | { 191 | DELETE(pMemPoolContainer); 192 | } 193 | else 194 | { 195 | CMemMonitor::getInstance().newMemPoolInfo(pMemPoolContainer, count, size + AddrSize); 196 | } 197 | } 198 | return ok; 199 | } 200 | 201 | void CMemManager::destroyPool(MemPoolContainer* pMemPoolContainer) 202 | { 203 | CMemMonitor::getInstance().deleteMemPoolInfo(pMemPoolContainer); 204 | 205 | DELETE(pMemPoolContainer); 206 | } 207 | 208 | 209 | // only for test code 210 | void CMemManager::output() 211 | { 212 | MemPoolContainer* pCur = m_pHeader; 213 | while (pCur != NULL) 214 | { 215 | pCur->memPool.output(); 216 | pCur = pCur->pNext; 217 | } 218 | } 219 | 220 | } 221 | 222 | -------------------------------------------------------------------------------- /common/base_lib/CMemManager.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.16 4 | * description : 自动内存块内存池管理,快速高效的获取、释放内存,防止内存碎片 5 | */ 6 | 7 | #ifndef CMEMMANAGER_H 8 | #define CMEMMANAGER_H 9 | 10 | namespace NCommon 11 | { 12 | 13 | struct MemPoolContainer; 14 | 15 | // 定长内存池管理 16 | class CMemManager 17 | { 18 | public: 19 | // 第一次分配count块长度为size的内存,用完则自动分配step块内存 20 | // 注意:count&step 的取值至少大于1,否则不会创建内存池 21 | CMemManager(const unsigned int count, const unsigned int step, const unsigned int size); 22 | ~CMemManager(); 23 | 24 | public: 25 | // 获取内存&释放内存 26 | char* get(); 27 | void put(char* p); 28 | 29 | public: 30 | void free(); // 释放空闲的内存池 31 | void clear(); // 释放所有内存池 32 | 33 | public: 34 | unsigned int getBuffSize() const; 35 | unsigned int getFreeCount() const; 36 | unsigned int getMaxCount() const; 37 | 38 | // 注意:step 的取值至少大于1,否则不会创建内存池 39 | void setStep(unsigned int step); 40 | unsigned int getStep() const; 41 | 42 | private: 43 | bool createPool(const unsigned int count, const unsigned int size, MemPoolContainer*& pMemPoolContainer); 44 | void destroyPool(MemPoolContainer* pMemPoolContainer); 45 | 46 | private: 47 | // 禁止拷贝、赋值 48 | CMemManager(); 49 | CMemManager(const CMemManager&); 50 | CMemManager& operator =(const CMemManager&); 51 | 52 | 53 | private: 54 | const unsigned int m_buffSize; 55 | unsigned int m_step; 56 | MemPoolContainer* m_pHeader; 57 | 58 | 59 | // only for test code 60 | public: 61 | void output(); 62 | }; 63 | 64 | } 65 | 66 | #endif // CMEMMANAGER_H 67 | -------------------------------------------------------------------------------- /common/base_lib/CMemMonitor.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.19 4 | * description : 内存监控、记录 5 | */ 6 | 7 | #include 8 | 9 | #include "MacroDefine.h" 10 | #include "CCfg.h" 11 | #include "CMemMonitor.h" 12 | 13 | 14 | namespace NCommon 15 | { 16 | 17 | CMemMonitor& CMemMonitor::getInstance() 18 | { 19 | static CMemMonitor instance; 20 | return instance; 21 | } 22 | 23 | int CMemMonitor::setOutputValue(const char* switchValue) 24 | { 25 | if (switchValue == NULL) 26 | { 27 | // 输出内存信息日志开关配置信息 28 | const char* loggerSection = "Logger"; 29 | const char* outputMemInfoSwitchItem = "OutputMemInfo"; 30 | switchValue = CCfg::getValue(loggerSection, outputMemInfoSwitchItem); 31 | } 32 | 33 | m_isOutput = (switchValue == NULL) ? 0 : atoi(switchValue); 34 | if (m_isOutput != 1) 35 | { 36 | // 关闭内存操作记录 37 | m_address2MemInfo.clear(); 38 | m_address2MemPoolInfo.clear(); 39 | } 40 | 41 | return m_isOutput; 42 | } 43 | 44 | void CMemMonitor::outputMemInfo() 45 | { 46 | if (m_isOutput != 1) return; 47 | 48 | const AddressToMemInfo& memInfo = getMemInfo(); 49 | typedef vector SMemInfoVector; 50 | typedef std::map TimeToSMemInfoMap; 51 | TimeToSMemInfoMap time2MemInfo; 52 | unsigned int memSize = 0; 53 | 54 | for (AddressToMemInfo::const_iterator memIt = memInfo.begin(); memIt != memInfo.end(); ++memIt) 55 | { 56 | memSize += memIt->second.size; 57 | time2MemInfo[memIt->second.time].push_back(&memIt->second); 58 | } 59 | 60 | const AddressToMemPoolInfo& memPoolInfo = getMemPoolInfo(); 61 | typedef vector SMemPoolVector; 62 | typedef std::map TimeToSMemPoolMap; 63 | TimeToSMemPoolMap time2MemPool; 64 | unsigned int poolSize = 0; 65 | 66 | for (AddressToMemPoolInfo::const_iterator memPoolIt = memPoolInfo.begin(); memPoolIt != memPoolInfo.end(); ++memPoolIt) 67 | { 68 | poolSize += (memPoolIt->second.size * memPoolIt->second.count); 69 | time2MemPool[memPoolIt->second.time].push_back(&memPoolIt->second); 70 | } 71 | 72 | ReleaseInfoLog("---------- begin output memory info ----------"); 73 | 74 | time_t lastTimeSecs = 0; 75 | for (TimeToSMemInfoMap::const_iterator tmIt = time2MemInfo.begin(); tmIt != time2MemInfo.end(); ++tmIt) 76 | { 77 | if (tmIt->first > lastTimeSecs) lastTimeSecs = tmIt->first; 78 | 79 | for (SMemInfoVector::const_iterator memIt = tmIt->second.begin(); memIt != tmIt->second.end(); ++memIt) 80 | { 81 | ReleaseInfoLog("mem|%u|%u|%u|%s", tmIt->first, (*memIt)->size, (*memIt)->line, (*memIt)->fileName.c_str()); 82 | } 83 | } 84 | 85 | for (TimeToSMemPoolMap::const_iterator tpIt = time2MemPool.begin(); tpIt != time2MemPool.end(); ++tpIt) 86 | { 87 | if (tpIt->first > lastTimeSecs) lastTimeSecs = tpIt->first; 88 | 89 | for (SMemPoolVector::const_iterator pIt = tpIt->second.begin(); pIt != tpIt->second.end(); ++pIt) 90 | { 91 | ReleaseInfoLog("pool|%u|%u|%u", tpIt->first, (*pIt)->size, (*pIt)->count); 92 | } 93 | } 94 | 95 | struct tm lastTimeInfo; 96 | struct tm* pLastTm = localtime_r(&lastTimeSecs, &lastTimeInfo); 97 | ReleaseInfoLog("memory stage info, last time = %u, [%d-%02d-%02d %02d:%02d:%02d], size = %u, count = %u, pool size = %u, count = %u, diff = %u", 98 | lastTimeSecs, (pLastTm->tm_year + 1900), (pLastTm->tm_mon + 1), pLastTm->tm_mday, pLastTm->tm_hour, pLastTm->tm_min, pLastTm->tm_sec, 99 | memSize, memInfo.size(), poolSize, memPoolInfo.size(), memSize - poolSize); 100 | 101 | const SMemOptStatInfo& memOptStatInfo = getMemOptStatInfo(); 102 | ReleaseInfoLog("memory all info, size = %u, new = %u, delete = %u, pool size = %u, new = %u, delete = %u, diff = %u", 103 | memOptStatInfo.allSize, memOptStatInfo.newCount, memOptStatInfo.delCount, 104 | memOptStatInfo.poolSize, memOptStatInfo.poolNew, memOptStatInfo.poolDel, 105 | memOptStatInfo.allSize - memOptStatInfo.poolSize); 106 | 107 | ReleaseInfoLog("---------- end output memory info ----------"); 108 | } 109 | 110 | } 111 | 112 | -------------------------------------------------------------------------------- /common/base_lib/CMemMonitor.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.19 4 | * description : 内存监控、记录 5 | */ 6 | 7 | #ifndef CMEMMONITOR_H 8 | #define CMEMMONITOR_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | using namespace std; 17 | 18 | namespace NCommon 19 | { 20 | 21 | // 内存信息 22 | struct SMemInfo 23 | { 24 | string fileName; 25 | unsigned int line; 26 | unsigned int size; 27 | unsigned int time; 28 | 29 | SMemInfo() {}; 30 | SMemInfo(const char* _fileName, unsigned int _line, unsigned int _size, unsigned int _time) : fileName(_fileName), line(_line), size(_size), time(_time) {}; 31 | ~SMemInfo() {}; 32 | }; 33 | typedef unordered_map AddressToMemInfo; 34 | 35 | 36 | // 内存池信息 37 | struct SMemPoolInfo 38 | { 39 | unsigned int count; 40 | unsigned int size; 41 | unsigned int time; 42 | 43 | SMemPoolInfo() {}; 44 | SMemPoolInfo(unsigned int _count, unsigned int _size, unsigned int _time) : count(_count), size(_size), time(_time) {}; 45 | ~SMemPoolInfo() {}; 46 | }; 47 | typedef unordered_map AddressToMemPoolInfo; 48 | 49 | 50 | // 内存操作统计信息 51 | struct SMemOptStatInfo 52 | { 53 | unsigned int newCount; 54 | unsigned int delCount; 55 | unsigned int allSize; 56 | 57 | unsigned int poolNew; 58 | unsigned int poolDel; 59 | unsigned int poolSize; 60 | 61 | SMemOptStatInfo() : newCount(0), delCount(0), allSize(0), poolNew(0), poolDel(0), poolSize(0) {}; 62 | ~SMemOptStatInfo() {}; 63 | }; 64 | 65 | 66 | class CMemMonitor 67 | { 68 | public: 69 | static CMemMonitor& getInstance(); 70 | 71 | public: 72 | int setOutputValue(const char* switchValue = NULL); 73 | void outputMemInfo(); 74 | 75 | public: 76 | inline const AddressToMemInfo& getMemInfo() 77 | { 78 | return m_address2MemInfo; 79 | } 80 | 81 | inline const AddressToMemPoolInfo& getMemPoolInfo() 82 | { 83 | return m_address2MemPoolInfo; 84 | } 85 | 86 | inline const SMemOptStatInfo& getMemOptStatInfo() 87 | { 88 | return m_memOptStatInfo; 89 | } 90 | 91 | public: 92 | inline void newMemInfo(const void* address, const char* fileName, unsigned int line, unsigned int size) 93 | { 94 | ++m_memOptStatInfo.newCount; 95 | m_memOptStatInfo.allSize += size; 96 | 97 | if (m_isOutput != 1) return; 98 | 99 | m_address2MemInfo[address] = SMemInfo(fileName, line, size, time(NULL)); 100 | } 101 | 102 | inline void deleteMemInfo(const void* address) 103 | { 104 | ++m_memOptStatInfo.delCount; 105 | 106 | if (m_isOutput != 1) return; 107 | 108 | m_address2MemInfo.erase(address); 109 | } 110 | 111 | inline void newMemPoolInfo(const void* address, unsigned int count, unsigned int size) 112 | { 113 | ++m_memOptStatInfo.poolNew; 114 | m_memOptStatInfo.poolSize += (count * size); 115 | 116 | if (m_isOutput != 1) return; 117 | 118 | m_address2MemPoolInfo[address] = SMemPoolInfo(count, size, time(NULL)); 119 | } 120 | 121 | inline void deleteMemPoolInfo(const void* address) 122 | { 123 | ++m_memOptStatInfo.poolDel; 124 | 125 | if (m_isOutput != 1) return; 126 | 127 | m_address2MemPoolInfo.erase(address); 128 | } 129 | 130 | private: 131 | int m_isOutput; 132 | AddressToMemInfo m_address2MemInfo; 133 | AddressToMemPoolInfo m_address2MemPoolInfo; 134 | SMemOptStatInfo m_memOptStatInfo; 135 | 136 | private: 137 | // 禁止拷贝、赋值 138 | CMemMonitor() : m_isOutput(1) {}; 139 | CMemMonitor(const CMemMonitor&); 140 | CMemMonitor& operator =(const CMemMonitor&); 141 | 142 | }; 143 | 144 | } 145 | 146 | #endif // CMEMMONITOR_H 147 | -------------------------------------------------------------------------------- /common/base_lib/CMemPool.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.20 4 | * description : 内存块内存池快速高效的获取访问,防止内存频繁操作导致内存碎片 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "CMemPool.h" 11 | #include "MacroDefine.h" 12 | 13 | 14 | namespace NCommon 15 | { 16 | typedef unsigned long pointer_t; // 32&64 位系统指针占用内存的长度都和 unsigned long 类型占用的长度相等 17 | static const int AddrSize = sizeof(char*); // 指针占用内存的长度 18 | 19 | // 内存池实现 20 | CMemPool::CMemPool(const unsigned int count, const unsigned int size) : m_maxCount(count), m_buffSize(size), m_freeCount(0) 21 | { 22 | m_pBuff = NULL; 23 | m_pHead = NULL; 24 | m_pLast = NULL; 25 | if (count <= 1 || size == 0) 26 | { 27 | return; 28 | } 29 | 30 | NEW_ARRAY(m_pBuff, char[(size + AddrSize) * count]); // 块buff的实际大小 (size + AddrSize) * count = 总内存大小 31 | } 32 | 33 | CMemPool::~CMemPool() 34 | { 35 | m_freeCount = 0; 36 | m_pHead = NULL; 37 | m_pLast = NULL; 38 | DELETE_ARRAY(m_pBuff); 39 | } 40 | 41 | bool CMemPool::init(void* data) 42 | { 43 | // 切片串成链表 44 | if (m_pBuff != NULL) 45 | { 46 | const unsigned int count = m_maxCount; 47 | const unsigned int len = m_buffSize + AddrSize; // 块buff的实际大小 48 | const unsigned int max = len * count; // 总内存大小 49 | 50 | memset(m_pBuff, 0, sizeof(char) * max); 51 | m_pLast = m_pBuff + len * (count - 1); 52 | 53 | char* pCur = NULL; 54 | char* pNext = NULL; 55 | for (unsigned int i = 0; i < count - 1; i++) 56 | { 57 | pCur = m_pBuff + len * i; // 当前buff块 58 | pNext = m_pBuff + len * (i + 1); // 下一块buff的起始地址 59 | *(pointer_t*)pCur = (pointer_t)pNext; // 存储在前一块buff的头部 60 | *(pointer_t*)(pCur + AddrSize) = (pointer_t)data; // 在头部存储用户数据 61 | } 62 | *(pointer_t*)(pNext + AddrSize) = (pointer_t)data; // 在头部存储用户数据,最后一个内存块 63 | 64 | m_pHead = m_pBuff; 65 | m_freeCount = count; 66 | return true; 67 | } 68 | 69 | return false; 70 | } 71 | 72 | char* CMemPool::get() 73 | { 74 | char* pRet = NULL; 75 | if (!empty()) 76 | { 77 | m_freeCount--; 78 | pRet = (m_pHead + AddrSize); // 用户buff的地址 79 | m_pHead = (char*)(*(pointer_t*)m_pHead); // 下一块buff的地址 80 | } 81 | return pRet; 82 | } 83 | 84 | bool CMemPool::put(char* p) 85 | { 86 | if (p != NULL) 87 | { 88 | p -= AddrSize; 89 | if (p < m_pBuff || p > m_pLast) // 地址范围判断 90 | { 91 | return false; 92 | } 93 | 94 | if (m_pHead != NULL) 95 | { 96 | *(pointer_t*)p = (pointer_t)m_pHead; 97 | } 98 | else 99 | { 100 | *(pointer_t*)p = 0; 101 | } 102 | m_pHead = p; 103 | m_freeCount++; 104 | } 105 | 106 | return true; 107 | } 108 | 109 | bool CMemPool::empty() const 110 | { 111 | return m_freeCount == 0; 112 | } 113 | 114 | bool CMemPool::full() const 115 | { 116 | return m_freeCount == m_maxCount; 117 | } 118 | 119 | unsigned int CMemPool::getFreeCount() const 120 | { 121 | return m_freeCount; 122 | } 123 | 124 | unsigned int CMemPool::getMaxCount() const 125 | { 126 | return m_maxCount; 127 | } 128 | 129 | unsigned int CMemPool::getBuffSize() const 130 | { 131 | return m_buffSize; 132 | } 133 | 134 | 135 | // only for test code 136 | void CMemPool::output() 137 | { 138 | char* p = m_pHead; 139 | while (p != NULL) 140 | { 141 | printf("--> %ld", (pointer_t)p); 142 | p = (char*)(*(pointer_t*)p); 143 | } 144 | printf("\n"); 145 | } 146 | 147 | } 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /common/base_lib/CMemPool.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.20 4 | * description : 内存块内存池快速高效的获取访问,防止内存频繁操作导致内存碎片 5 | */ 6 | 7 | #ifndef CMEM_POOL_H 8 | #define CMEM_POOL_H 9 | 10 | namespace NCommon 11 | { 12 | // 内存池实现 13 | class CMemPool 14 | { 15 | public: 16 | // 创建count块内存,每块内存size大小的字节 17 | CMemPool(const unsigned int count, const unsigned int size); 18 | bool init(void* data = 0); 19 | 20 | ~CMemPool(); 21 | 22 | public: 23 | // 获取内存&释放内存 24 | char* get(); 25 | bool put(char* p); 26 | 27 | public: 28 | bool empty() const; 29 | bool full() const; 30 | unsigned int getFreeCount() const; 31 | unsigned int getMaxCount() const; 32 | unsigned int getBuffSize() const; 33 | 34 | private: 35 | // 禁止拷贝、赋值 36 | CMemPool(); 37 | CMemPool(const CMemPool&); 38 | CMemPool& operator =(const CMemPool&); 39 | 40 | private: 41 | const unsigned int m_maxCount; 42 | const unsigned int m_buffSize; 43 | 44 | private: 45 | char* m_pBuff; 46 | char* m_pHead; 47 | char* m_pLast; 48 | unsigned int m_freeCount; 49 | 50 | 51 | // only for test code 52 | public: 53 | void output(); 54 | }; 55 | 56 | } 57 | 58 | #endif // CMEM_POOL_H 59 | 60 | -------------------------------------------------------------------------------- /common/base_lib/CMessageQueue.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.17 4 | * description : 消息队列操作,单线程读&单线程写免锁 5 | */ 6 | 7 | #ifndef CMESSAGEQUEUE_H 8 | #define CMESSAGEQUEUE_H 9 | 10 | #include "MacroDefine.h" 11 | #include "Type.h" 12 | 13 | 14 | namespace NCommon 15 | { 16 | 17 | // 码流消息队列操作 ,公共API 18 | class CMessageQueue 19 | { 20 | public: 21 | // 输入&输出数据,会产生一次数据拷贝过程 22 | static int write(char* pShmWrite, PkgQueue& shmQueue, const char* pData, const int len); 23 | static int read(char* pShmRead, PkgQueue& shmQueue, char* pData, int& rLen); 24 | 25 | public: 26 | // 获取buff,用于直接写入数据到该buff中 27 | static int beginWriteBuff(char* pShmWrite, const PkgQueue& shmQueue, char*& pBuff, const int len); // len:申请buff的长度 28 | static int endWriteBuff(char* pShmWrite, PkgQueue& shmQueue, const char* pBuff, const int len); // len:实际写入的数据长度 29 | 30 | // 获取buff,用于直接读取该buff中的数据 31 | static int beginReadBuff(char* pShmRead, const PkgQueue& shmQueue, char*& pBuff, int& len); // len:buff中数据包长度 32 | static int endReadBuff(char* pShmRead, PkgQueue& shmQueue, const char* pBuff, const int len); // len:buff数据长度 33 | 34 | public: 35 | // 查看消息队列是否可读写消息 36 | static int readyWrite(char* pShmWrite, const PkgQueue& shmQueue, const int len); 37 | static int readyRead(char* pShmRead, const PkgQueue& shmQueue); 38 | 39 | private: 40 | // 调整数据队列读写点索引 41 | static int adjustWriteIdx(const PkgQueue& queue, const int needLen, char* pWrite, int& curWrite); 42 | static int adjustReadIdx(const PkgQueue& queue, const char* pRead, int& curRead); 43 | 44 | DISABLE_CLASS_BASE_FUNC(CMessageQueue); // 禁止实例化对象 45 | }; 46 | 47 | 48 | 49 | // 指针消息队列,公共API 50 | class CAddressQueue 51 | { 52 | public: 53 | CAddressQueue(); 54 | CAddressQueue(unsigned int size); 55 | ~CAddressQueue(); 56 | 57 | public: 58 | void resetSize(unsigned int size); 59 | unsigned int getSize(); 60 | 61 | public: 62 | bool put(void* pData); 63 | void* get(); 64 | bool have(); 65 | 66 | public: 67 | void clear(); // 清空消息 68 | unsigned int check(void* pCheckData); // 检查当前消息队列中存在此消息的个数 69 | 70 | private: 71 | void** m_pBuff; // 消息缓冲区 72 | unsigned int m_size; // 队列容量 73 | 74 | private: 75 | // 读写队列索引 76 | volatile unsigned int m_write; 77 | volatile unsigned int m_read; 78 | 79 | DISABLE_COPY_ASSIGN(CAddressQueue); 80 | }; 81 | 82 | } 83 | 84 | #endif // CMESSAGEQUEUE_H 85 | -------------------------------------------------------------------------------- /common/base_lib/CMultiW_SingleR_Queue.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.07 4 | * description : 多线程写,单线程读队列,读免锁 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "CMultiW_SingleR_Queue.h" 12 | #include "MacroDefine.h" 13 | #include "ErrorCode.h" 14 | #include "CLock.h" 15 | 16 | 17 | using namespace NErrorCode; 18 | 19 | namespace NCommon 20 | { 21 | 22 | CMultiW_SingleR_Queue::CMultiW_SingleR_Queue(int size) 23 | { 24 | m_size = size; 25 | NEW_ARRAY(m_pBuff, char*[size]); 26 | memset(m_pBuff, 0, sizeof(char*) * size); 27 | m_write = 1; // 开始写点 28 | m_read = 0; // 开始读点 29 | m_isWaitNotify = 0; 30 | } 31 | 32 | CMultiW_SingleR_Queue::~CMultiW_SingleR_Queue() 33 | { 34 | m_size = 0; 35 | DELETE_ARRAY(m_pBuff); 36 | m_pBuff = NULL; 37 | m_write = 1; 38 | m_read = 0; 39 | m_isWaitNotify = 0; 40 | } 41 | 42 | int CMultiW_SingleR_Queue::waitNotify(int ms) 43 | { 44 | int rc = 0; 45 | if (ms <= 0) 46 | { 47 | rc = m_notifyCond.wait(m_notifyMutex); 48 | } 49 | else 50 | { 51 | struct timespec abstime; 52 | struct timeval now; 53 | (void)gettimeofday(&now, NULL); 54 | long nsec = now.tv_usec * 1000 + (ms % 1000) * 1000000; // 转换为纳秒 55 | abstime.tv_nsec = nsec % 1000000000; // 剩余纳秒 56 | abstime.tv_sec = now.tv_sec + (nsec / 1000000000) + (ms / 1000); // 转换为当前秒 57 | rc = m_notifyCond.timedWait(m_notifyMutex, &abstime); 58 | } 59 | 60 | return rc; 61 | } 62 | 63 | void CMultiW_SingleR_Queue::notify() 64 | { 65 | // !!!这里必须先加锁,否则存在唤醒事件丢失的情况(不加锁则可能唤醒事件提前触发,导致等待线程死等) 66 | m_notifyMutex.lock(); 67 | m_notifyCond.signal(); 68 | m_notifyMutex.unLock(); 69 | } 70 | 71 | int CMultiW_SingleR_Queue::put(char* pData) 72 | { 73 | int rc = Success; 74 | if (pData != NULL) 75 | { 76 | m_writeMutex.lock(); 77 | if (m_pBuff[m_write] == NULL) // 读点在并发中不断变化,因此只能判断数据,不能依据读写点判断是否为满队列 78 | { 79 | // 理论上不保证读取m_read的值是原子操作,尤其是在多cpu多核的机器上 80 | // 下一个读点没有数据,则之前队列可能为空,读线程有可能是在等待 81 | // !!!放入数据之前做判断 82 | bool isWaitNotify = (m_pBuff[(m_read + 1) % m_size] == NULL); 83 | 84 | m_pBuff[m_write] = pData; 85 | m_write = (m_write + 1) % m_size; // 下一个写点 86 | m_writeMutex.unLock(); 87 | 88 | if (m_isWaitNotify || isWaitNotify) // 双重判断,更保险一些 89 | { 90 | notify(); 91 | } 92 | } 93 | else 94 | { 95 | m_writeMutex.unLock(); 96 | rc = QueueFull; // 队列满 97 | } 98 | } 99 | 100 | return rc; 101 | } 102 | 103 | // 队列空时读线程阻塞等待ms毫秒的时间,单位毫秒,默认值0表示永久等待直到被消息入队列唤醒 104 | char* CMultiW_SingleR_Queue::get(int ms) 105 | { 106 | int nextRead = (m_read + 1) % m_size; 107 | 108 | // 写点在并发中不断变化,因此只能判断数据,依据读写点判断是否为空队列不准确,但可以考虑和数据一起做判断 109 | // 由于并发可能存在put()函数中pBuff[m_write] = pData;语句没有完全赋值完,就被这里读到的情况 110 | // 可以考虑增加读写点一起做判断 111 | char* pData = m_pBuff[nextRead]; 112 | if (pData == NULL) 113 | { 114 | m_notifyMutex.lock(); // 锁定等待数据入队列 115 | m_isWaitNotify = 1; // 需要消息唤醒通知 116 | pData = m_pBuff[nextRead]; // !!!这里必须重新再取一次,有可能通知事件已经提前触发了,因此数据已经存在了,否则这种情况下将导致线程死等 117 | while (pData == NULL) 118 | { 119 | int rc = waitNotify(ms); 120 | pData = m_pBuff[nextRead]; 121 | if (ETIMEDOUT == rc) // 等待超时则退出 122 | { 123 | break; 124 | } 125 | } 126 | m_isWaitNotify = 0; 127 | m_notifyMutex.unLock(); 128 | 129 | if (pData == NULL) // 等待超时无数据 130 | { 131 | return NULL; 132 | } 133 | } 134 | m_pBuff[nextRead] = NULL; 135 | m_read = nextRead; 136 | 137 | return pData; 138 | } 139 | 140 | } 141 | 142 | -------------------------------------------------------------------------------- /common/base_lib/CMultiW_SingleR_Queue.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.07 4 | * description : 多线程写,单线程读队列,读免锁 5 | */ 6 | 7 | #ifndef CMULTIW_SINGLER_QUEUE_H 8 | #define CMULTIW_SINGLER_QUEUE_H 9 | 10 | #include "CMutex.h" 11 | #include "CCond.h" 12 | 13 | namespace NCommon 14 | { 15 | 16 | class CMultiW_SingleR_Queue 17 | { 18 | public: 19 | CMultiW_SingleR_Queue(int size); 20 | ~CMultiW_SingleR_Queue(); 21 | 22 | public: 23 | int put(char* pData); 24 | char* get(int ms = 0); // 队列空时读线程阻塞等待的时间,单位毫秒,默认值0表示永久等待直到被消息入队列唤醒 25 | 26 | private: 27 | int waitNotify(int ms); 28 | void notify(); 29 | 30 | private: 31 | // 禁止拷贝、赋值 32 | CMultiW_SingleR_Queue(); 33 | CMultiW_SingleR_Queue(const CMultiW_SingleR_Queue&); 34 | CMultiW_SingleR_Queue& operator =(const CMultiW_SingleR_Queue&); 35 | 36 | private: 37 | CMutex m_writeMutex; // 写锁 38 | CMutex m_notifyMutex; // 队列空、满等待锁 39 | CCond m_notifyCond; // 队列空、满等待条件 40 | volatile char m_isWaitNotify; // 读线程是否在等待数据 41 | 42 | private: 43 | char** m_pBuff; // 消息缓冲区 44 | int m_size; // 队列容量 45 | 46 | private: 47 | // 读写队列索引 48 | volatile int m_write; 49 | volatile int m_read; 50 | }; 51 | 52 | } 53 | 54 | #endif // CMULTIW_SINGLER_QUEUE_H 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /common/base_lib/CMutex.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.19 4 | * description : 互斥锁API封装 5 | */ 6 | 7 | #include 8 | 9 | #include "CMutex.h" 10 | #include "MacroDefine.h" 11 | 12 | 13 | namespace NCommon 14 | { 15 | 16 | CMutex::CMutex(MutexType mutexType) 17 | { 18 | int rc = pthread_mutexattr_init(&m_mutexAttr); 19 | if (rc != 0) 20 | { 21 | ReleaseErrorLog("call pthread_mutexattr_init error = %d, info = %s", rc, strerror(rc)); // 运行日志 22 | } 23 | 24 | else if (mutexType != defaultMutexType) 25 | { 26 | rc = pthread_mutexattr_setpshared(&m_mutexAttr, mutexType); 27 | if (rc != 0) 28 | { 29 | ReleaseErrorLog("call pthread_mutexattr_setpshared error = %d, info = %s, mutex type = %d", rc, strerror(rc), mutexType); 30 | } 31 | } 32 | 33 | rc = pthread_mutex_init(&m_mutex, &m_mutexAttr); 34 | if (rc != 0) 35 | { 36 | ReleaseErrorLog("call pthread_mutex_init error = %d, info = %s", rc, strerror(rc)); // 运行日志 37 | } 38 | } 39 | 40 | CMutex::~CMutex() 41 | { 42 | pthread_mutex_destroy(&m_mutex); 43 | pthread_mutexattr_destroy(&m_mutexAttr); 44 | } 45 | 46 | int CMutex::lock() 47 | { 48 | return pthread_mutex_lock(&m_mutex); 49 | } 50 | 51 | int CMutex::tryLock() 52 | { 53 | return pthread_mutex_trylock(&m_mutex); 54 | } 55 | 56 | int CMutex::unLock() 57 | { 58 | return pthread_mutex_unlock(&m_mutex); 59 | } 60 | 61 | pthread_mutex_t* CMutex::get_mutex() 62 | { 63 | return &m_mutex; 64 | } 65 | 66 | } 67 | 68 | 69 | -------------------------------------------------------------------------------- /common/base_lib/CMutex.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.19 4 | * description : 互斥锁API封装 5 | */ 6 | 7 | #ifndef CMUTEX_H 8 | #define CMUTEX_H 9 | 10 | #include 11 | 12 | 13 | namespace NCommon 14 | { 15 | 16 | // 锁类型 17 | enum MutexType 18 | { 19 | defaultMutexType = PTHREAD_MUTEX_DEFAULT, // 默认属性 20 | recursiveMutexType = PTHREAD_MUTEX_RECURSIVE, // 独占递归锁 21 | recursiveNPMutexType = PTHREAD_MUTEX_RECURSIVE_NP, // 抢占递归锁 22 | sharedMutexType = PTHREAD_PROCESS_SHARED, // 进程间共享锁 23 | }; 24 | 25 | class CMutex 26 | { 27 | public: 28 | CMutex(MutexType mutexType = defaultMutexType); 29 | ~CMutex(); 30 | 31 | public: 32 | int lock(); 33 | int tryLock(); 34 | int unLock(); 35 | pthread_mutex_t* get_mutex(); 36 | 37 | private: 38 | // 禁止拷贝、赋值 39 | CMutex(const CMutex&); 40 | CMutex& operator =(const CMutex&); 41 | 42 | private: 43 | pthread_mutexattr_t m_mutexAttr; // 为了支持以后好扩展使用 44 | pthread_mutex_t m_mutex; 45 | }; 46 | 47 | } 48 | 49 | #endif // CMUTEX_H 50 | 51 | 52 | -------------------------------------------------------------------------------- /common/base_lib/CProcess.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.02.06 4 | * description : 进程管理操作 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "CProcess.h" 11 | #include "ErrorCode.h" 12 | 13 | 14 | using namespace NErrorCode; 15 | 16 | namespace NCommon 17 | { 18 | 19 | // 安装信号处理函数 20 | int CProcess::installSignal(int sigNum, SignalHandler handler) 21 | { 22 | struct sigaction sigAction; 23 | sigAction.sa_sigaction = handler; 24 | sigemptyset(&sigAction.sa_mask); 25 | sigAction.sa_flags = SA_SIGINFO; 26 | if (sigaction(sigNum, &sigAction, NULL) != 0) 27 | { 28 | ReleaseErrorLog("install signal handler = %d, error = %d, info = %s", sigNum, errno, strerror(errno)); 29 | return SystemCallErr; 30 | } 31 | 32 | return Success; 33 | } 34 | 35 | // 忽略信号 36 | int CProcess::ignoreSignal(int sigNum) 37 | { 38 | struct sigaction sigAction; 39 | sigAction.sa_handler = SIG_IGN; 40 | sigemptyset(&sigAction.sa_mask); 41 | sigAction.sa_flags = 0; 42 | if (sigaction(sigNum, &sigAction, NULL) != 0) 43 | { 44 | ReleaseErrorLog("ignore signal = %d, error = %d, info = %s", sigNum, errno, strerror(errno)); 45 | return SystemCallErr; 46 | } 47 | 48 | return Success; 49 | } 50 | 51 | // 把进程转变为守护进程 52 | int CProcess::toDaemon() 53 | { 54 | return SystemCallErr; 55 | } 56 | 57 | // 执行命令 58 | int CProcess::doCommand(const char* cmd) 59 | { 60 | if (cmd == NULL || *cmd == '\0') return InvalidParam; 61 | 62 | errno = 0; 63 | const int status = ::system(cmd); 64 | const bool isOk = (WIFEXITED(status) && WEXITSTATUS(status) == 0); 65 | if (!isOk) 66 | { 67 | ReleaseErrorLog("call system do command error, cmd = %s, status = %d, error = %d, info = %s", cmd, status, errno, strerror(errno)); 68 | 69 | return SystemCallErr; 70 | } 71 | 72 | return Success; 73 | } 74 | 75 | } 76 | 77 | -------------------------------------------------------------------------------- /common/base_lib/CProcess.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.02.06 4 | * description : 进程管理操作 5 | */ 6 | 7 | #ifndef CPROCESS_H 8 | #define CPROCESS_H 9 | 10 | #include 11 | #include "MacroDefine.h" 12 | 13 | 14 | typedef void (*SignalHandler)(int sigNum, siginfo_t* sigInfo, void* context); // 信号处理函数 15 | 16 | namespace NCommon 17 | { 18 | 19 | // 进程接收的信号值 20 | namespace SignalNumber 21 | { 22 | static const int ReloadConfig = SIGRTMIN + 1; // 更新配置文件 23 | static const int StopProcess = SIGRTMIN + 2; // 停止退出进程 24 | }; 25 | 26 | 27 | class CProcess 28 | { 29 | public: 30 | // 安装信号处理函数 31 | static int installSignal(int sigNum, SignalHandler handler); 32 | 33 | // 忽略信号 34 | static int ignoreSignal(int sigNum); 35 | 36 | // 把进程转变为守护进程 37 | static int toDaemon(); 38 | 39 | // 执行命令 40 | static int doCommand(const char* cmd); 41 | 42 | 43 | DISABLE_CLASS_BASE_FUNC(CProcess); // 禁止实例化对象 44 | }; 45 | 46 | } 47 | 48 | #endif // CPROCESS_H 49 | -------------------------------------------------------------------------------- /common/base_lib/CRefObj.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.12.03 4 | * description : 对象自动管理,引用计数 5 | */ 6 | 7 | #include "CRefObj.h" 8 | #include "MacroDefine.h" 9 | 10 | 11 | namespace NCommon 12 | { 13 | 14 | CRefObj::CRefObj() 15 | { 16 | m_ref = 0; 17 | } 18 | 19 | CRefObj::~CRefObj() 20 | { 21 | m_ref = -1; 22 | } 23 | 24 | int CRefObj::addRef() 25 | { 26 | return ++m_ref; 27 | } 28 | 29 | int CRefObj::releaseRef() 30 | { 31 | int ref = --m_ref; 32 | if (ref <= 0) 33 | { 34 | CRefObj* pThis = this; 35 | DELETE(pThis); 36 | } 37 | 38 | return ref; 39 | } 40 | 41 | int CRefObj::getRef() const 42 | { 43 | return m_ref; 44 | } 45 | 46 | 47 | 48 | CAutoMgrInstance::CAutoMgrInstance(CRefObj* refInstance) : m_refInstance(refInstance) 49 | { 50 | if (m_refInstance != NULL) m_refInstance->addRef(); 51 | } 52 | 53 | CAutoMgrInstance::CAutoMgrInstance(const CAutoMgrInstance& obj) : m_refInstance(obj.m_refInstance) 54 | { 55 | if (m_refInstance != NULL) m_refInstance->addRef(); 56 | } 57 | 58 | CAutoMgrInstance::~CAutoMgrInstance() 59 | { 60 | if (m_refInstance != NULL) 61 | { 62 | m_refInstance->releaseRef(); 63 | m_refInstance = NULL; 64 | } 65 | } 66 | 67 | int CAutoMgrInstance::getRef() const 68 | { 69 | return (m_refInstance != NULL) ? m_refInstance->getRef() : -1; 70 | } 71 | 72 | CRefObj* CAutoMgrInstance::getInstance() 73 | { 74 | return m_refInstance; 75 | } 76 | 77 | } 78 | 79 | -------------------------------------------------------------------------------- /common/base_lib/CRefObj.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.12.03 4 | * description : 对象自动管理,引用计数 5 | */ 6 | 7 | #ifndef CREFOBJ_H 8 | #define CREFOBJ_H 9 | 10 | namespace NCommon 11 | { 12 | // 对象自管理,引用计数 13 | class CRefObj 14 | { 15 | public: 16 | int addRef(); 17 | int releaseRef(); 18 | int getRef() const; 19 | 20 | protected: 21 | CRefObj(); 22 | virtual ~CRefObj(); 23 | 24 | private: 25 | // 禁止拷贝、赋值 26 | CRefObj(const CRefObj&); 27 | CRefObj& operator =(const CRefObj&); 28 | 29 | private: 30 | int m_ref; 31 | }; 32 | 33 | 34 | // 自动管理对象,智能对象 35 | // 会自动销户引用计数对象,管理对象的生命周期 36 | class CAutoMgrInstance 37 | { 38 | public: 39 | int getRef() const; 40 | CRefObj* getInstance(); 41 | 42 | public: 43 | CAutoMgrInstance(CRefObj* refInstance); 44 | CAutoMgrInstance(const CAutoMgrInstance& obj); 45 | ~CAutoMgrInstance(); 46 | 47 | private: 48 | // 禁止拷贝、赋值 49 | CAutoMgrInstance& operator =(const CAutoMgrInstance&); 50 | CAutoMgrInstance(CRefObj& refInstance); 51 | CAutoMgrInstance(CRefObj); 52 | 53 | private: 54 | CRefObj* m_refInstance; 55 | }; 56 | 57 | } 58 | 59 | #endif // CREFOBJ_H 60 | -------------------------------------------------------------------------------- /common/base_lib/CShm.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.17 4 | * description : 共享内存操作,共享内存管理进程间通信实现 5 | */ 6 | 7 | #ifndef CSHM_H 8 | #define CSHM_H 9 | 10 | #include "MacroDefine.h" 11 | #include "Type.h" 12 | 13 | 14 | namespace NCommon 15 | { 16 | 17 | // 共享内存操作,公共API 18 | class CSharedMemory 19 | { 20 | public: 21 | static int getKey(const char* keyFile); // 利用文件node id做为共享内存key,保证key唯一性 22 | static int lockFile(const char* keyFile, int lockPos, int& fd); // 加锁共享内存对应的key文件,防止进程重复初始化共享内存 23 | static int unLockFile(int fd, int lockPos); // 解锁共享内存key对应的文件 24 | 25 | public: 26 | static int create(int key, ulong64_t size, int flag, int& isCreate, int& shmId, char*& pShm); // 进程向操作系统申请共享内存空间 27 | static int atShm(int key, int& shmId, char*& pShm); // 挂接共享内存 28 | static int release(void*& shm); // 进程脱离共享内存 29 | 30 | DISABLE_CLASS_BASE_FUNC(CSharedMemory); // 禁止实例化对象 31 | }; 32 | 33 | 34 | 35 | static const int SIDE_COUNT = 2; // 通信两端 36 | 37 | // 共享内存头 38 | struct ShmHeader 39 | { 40 | unsigned int processLogicId[SIDE_COUNT]; // 通信两端的进程逻辑ID 41 | PkgQueue queue[SIDE_COUNT]; // 收发数据队列 42 | }; 43 | 44 | // 本进程内共享内存信息 45 | struct ShmInfo 46 | { 47 | int id; // 共享内存id值 48 | int key; // 共享内存key值 49 | ShmHeader* shmHeader; // 共享内存头部地址 50 | char* queue[SIDE_COUNT]; // 共享内存中收发数据队列开始地址 51 | int writeQueue; // 发数据队列索引 52 | int readQueue; // 收数据队列索引 53 | }; 54 | 55 | // 两两进程间共享内存通信 56 | class CShm 57 | { 58 | public: 59 | CShm(); 60 | ~CShm(); 61 | 62 | public: 63 | // 只读打开共享内存,以便跟踪共享内存统计数据信息 64 | int trace(const unsigned int srcId, const unsigned int dstId, const ulong64_t size); 65 | 66 | // 打开共享内存,不存在则创建 67 | // srcId为本进程逻辑ID,dstId为通信对端进程逻辑ID 68 | // size为共享内存大小,实际会分配2倍size大小的共享内存,分别为读写数据2条队列 69 | // 每个进程只能调用open一次,多次操作将返回失败 70 | // 在进程1打开一个和进程2通信的共享内存:open(1, 2, 10240 * 1024) 71 | int open(const unsigned int srcId, const unsigned int dstId, const ulong64_t size); 72 | 73 | // 此处不会调用shmctl删除共享内存,否则其他进程将映射不到该共享内存空间 74 | // 共享内存为双方通信进程共用,因此需要外部确认而手动删除 75 | int close(); 76 | 77 | // 输出共享内存信息到运行日志 78 | void output(); 79 | 80 | // 共享内存双队列,通信双方都是单读单写模式,因此读写都不加锁 81 | // 但理论上是需要加共享锁的,除非对int类型的读写操作是原子的 82 | public: 83 | // 从共享内存区输入&输出数据,会产生一次数据拷贝过程,必须配对使用 84 | int write(const char* pData, const int len); 85 | int read(char* pData, int& rLen); 86 | 87 | // 直接读写共享内存区,无数据拷贝过程,必须配对使用 88 | public: 89 | // 获取共享内存区buff,用于直接写入数据到该buff中 90 | int beginWriteBuff(char*& pBuff, const int len); // len:申请buff的长度 91 | int endWriteBuff(const char* pBuff, const int len); // len:实际写入的数据长度 92 | 93 | // 获取共享内存区buff,用于直接读取该buff中的数据 94 | int beginReadBuff(char*& pBuff, int& len); // len:buff中数据包长度 95 | int endReadBuff(const char* pBuff, const int len); // len:buff数据长度 96 | 97 | private: 98 | // 打开共享内存 99 | // srcId为本进程逻辑ID,dstId为通信对端进程逻辑ID 100 | // size为共享内存大小,实际会分配2倍size大小的共享内存,分别为2读写数据队列 101 | // isCreate如果为true则不存在就创建共享内存 102 | // 每个进程只能调用open一次,多次操作将返回失败 103 | // 在进程1打开一个和进程2通信的共享内存:open(1, 2, 10240 * 1024) 104 | int open(const unsigned int srcId, const unsigned int dstId, const ulong64_t size, const int isCreate); 105 | 106 | private: 107 | // 禁止拷贝、赋值 108 | CShm(const CShm&); 109 | CShm& operator =(const CShm&); 110 | 111 | private: 112 | ShmInfo m_shmInfo; 113 | }; 114 | 115 | } 116 | 117 | #endif // CSHM_H 118 | -------------------------------------------------------------------------------- /common/base_lib/CSingleW_SingleR_Buffer.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.27 4 | * description : 单线程写,单线程读字节码流缓冲区,读写免锁 5 | */ 6 | 7 | #include "CSingleW_SingleR_Buffer.h" 8 | 9 | namespace NCommon 10 | { 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /common/base_lib/CSingleW_SingleR_Buffer.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.27 4 | * description : 单线程写,单线程读字节码流缓冲区,读写免锁 5 | */ 6 | 7 | #ifndef CSINGLEW_SINGLER_BUFFER_H 8 | #define CSINGLEW_SINGLER_BUFFER_H 9 | 10 | #include 11 | #include "MacroDefine.h" 12 | 13 | 14 | namespace NCommon 15 | { 16 | 17 | // 单线程写,单线程读字节码流缓冲区,读写免锁 18 | // 读写数据缓冲区,注意字节对齐 19 | struct CSingleW_SingleR_Buffer 20 | { 21 | CSingleW_SingleR_Buffer* next; // 下一块可读写的buff 22 | char* buff; // 缓冲区开始地址 23 | unsigned int buffSize; // 缓冲区buff的大小 24 | 25 | // 读写索引 26 | volatile unsigned int readIdx; 27 | volatile unsigned int writeIdx; 28 | 29 | // 统计数据 30 | // unsigned int msgCount; 31 | // unsigned int msgSize; 32 | 33 | // 直接获取写缓冲区 34 | // 写数据时必须先写第一块数据区,写完了才能继续写第二块数据区,否则会直接导致错误 35 | inline bool beginWriteBuff(char*& firstBuff, unsigned int& firstLen, char*& secondBuff, unsigned int& secondLen) const 36 | { 37 | // 一次性拷贝读写索引,防止读写线程并发修改发生变化而导致错误 38 | unsigned int rdIdx = readIdx; 39 | unsigned int wtIdx = writeIdx; 40 | 41 | // 注意:rdIdx + 1 == wtIdx 则队列满,因此需要留出一个字节的空位 42 | // 否则存在当读线程读数据的时候,如果写线程正好把数据写满导致 rdIdx == wtIdx,会使得读线程误判断为空队列错误 43 | secondBuff = NULL; 44 | secondLen = 0; 45 | if (wtIdx < rdIdx) 46 | { 47 | firstBuff = buff + wtIdx; 48 | firstLen = rdIdx - wtIdx - 1; // 留出一个字节的空位 49 | } 50 | else 51 | { 52 | // rdIdx == wtIdx 情况则队列空 53 | firstBuff = buff + wtIdx; 54 | firstLen = buffSize - wtIdx; 55 | if (firstLen < 1 && rdIdx > 0) 56 | { 57 | firstBuff = buff; // 调整到队列头部 58 | firstLen = rdIdx - 1; // 留出一个字节的空位 59 | } 60 | else if (rdIdx > 0) 61 | { 62 | secondBuff = buff; 63 | secondLen = rdIdx - 1; // 留出一个字节的空位 64 | } 65 | } 66 | 67 | return (firstLen > 0); // 有可能队列数据满了 68 | } 69 | 70 | // 结束写入数据,必须配对beginWriteBuff调用 71 | inline void endWriteBuff(char* firstBuff, unsigned int firstLen, char* secondBuff, unsigned int secondLen) 72 | { 73 | if (secondLen > 0) 74 | { 75 | writeIdx = secondLen; 76 | } 77 | else if (firstLen > 0) 78 | { 79 | writeIdx = firstBuff - buff + firstLen; 80 | } 81 | } 82 | 83 | 84 | // 直接获取读缓冲区 85 | // 读数据时必须先读第一块数据区,读完了才能继续读第二块数据区,否则会直接导致错误 86 | inline bool beginReadBuff(char*& firstBuff, unsigned int& firstLen, char*& secondBuff, unsigned int& secondLen) const 87 | { 88 | // 一次性拷贝读写索引,防止读写线程并发修改发生变化而导致错误 89 | unsigned int rdIdx = readIdx; 90 | unsigned int wtIdx = writeIdx; 91 | 92 | firstBuff = NULL; 93 | firstLen = 0; 94 | secondBuff = NULL; 95 | secondLen = 0; 96 | if (rdIdx < wtIdx) 97 | { 98 | firstBuff = buff + rdIdx; 99 | firstLen = wtIdx - rdIdx; 100 | } 101 | else if (rdIdx > wtIdx) 102 | { 103 | firstBuff = buff + rdIdx; 104 | firstLen = buffSize - rdIdx; 105 | if (firstLen < 1 && wtIdx > 0) 106 | { 107 | firstBuff = buff; // 调整到队列头部 108 | firstLen = wtIdx; 109 | } 110 | else if (wtIdx > 0) 111 | { 112 | secondBuff = buff; 113 | secondLen = wtIdx; 114 | } 115 | } // rdIdx == wtIdx 情况则队列空 116 | 117 | return (firstLen > 0); // 有可能队列数据是空的 118 | } 119 | 120 | // 结束读取数据,必须配对beginReadBuff调用 121 | inline void endReadBuff(char* firstBuff, unsigned int firstLen, char* secondBuff, unsigned int secondLen) 122 | { 123 | if (secondLen > 0) 124 | { 125 | readIdx = secondLen; 126 | } 127 | else if (firstLen > 0) 128 | { 129 | readIdx = firstBuff - buff + firstLen; 130 | } 131 | } 132 | 133 | // 写入缓冲区,返回实际写入的数据长度 134 | // incompleteWrite : 缓冲区不够写时,是否强制写入,即不完全拷贝数据到写缓冲区 135 | inline unsigned int write(const char* data, const unsigned int len, bool incompleteWrite = true) 136 | { 137 | unsigned int freeSize = getFreeSize(); 138 | if (freeSize == 0 || (!incompleteWrite && freeSize < len)) 139 | { 140 | return 0; 141 | } 142 | 143 | char* firstBuff = NULL; 144 | unsigned int firstLen = 0; 145 | char* secondBuff = NULL; 146 | unsigned int secondLen = 0; 147 | if (!beginWriteBuff(firstBuff, firstLen, secondBuff, secondLen)) 148 | { 149 | return 0; 150 | } 151 | 152 | unsigned int cpLen = len < firstLen ? len : firstLen; 153 | memcpy(firstBuff, data, cpLen); 154 | endWriteBuff(firstBuff, cpLen, NULL, 0); 155 | 156 | if (cpLen < len && secondLen > 0) 157 | { 158 | unsigned int secondCpLen = len - cpLen; 159 | secondCpLen = secondCpLen < secondLen ? secondCpLen : secondLen; 160 | memcpy(secondBuff, data + cpLen, secondCpLen); 161 | endWriteBuff(NULL, 0, secondBuff, secondCpLen); 162 | cpLen += secondCpLen; 163 | } 164 | 165 | return cpLen; 166 | } 167 | 168 | // 从缓冲区读,返回实际读出的数据长度 169 | // isCopy : 为false时不会拷贝数据到调用者空间,相当于直接丢弃数据 170 | // incompleteRead : 缓冲区数据不够读时,是否强制读出,即不完全拷贝读出数据到用户空间 171 | inline unsigned int read(char* data, const unsigned int len, bool isCopy = true, bool incompleteRead = true) 172 | { 173 | unsigned int dataSize = getDataSize(); 174 | if (dataSize == 0 || (!incompleteRead && dataSize < len)) 175 | { 176 | return 0; 177 | } 178 | 179 | char* firstBuff = NULL; 180 | unsigned int firstLen = 0; 181 | char* secondBuff = NULL; 182 | unsigned int secondLen = 0; 183 | if (!beginReadBuff(firstBuff, firstLen, secondBuff, secondLen)) 184 | { 185 | return 0; 186 | } 187 | 188 | unsigned int cpLen = len < firstLen ? len : firstLen; 189 | if (isCopy) memcpy(data, firstBuff, cpLen); 190 | endReadBuff(firstBuff, cpLen, NULL, 0); 191 | 192 | if (cpLen < len && secondLen > 0) 193 | { 194 | unsigned int secondCpLen = len - cpLen; 195 | secondCpLen = secondCpLen < secondLen ? secondCpLen : secondLen; 196 | if (isCopy) memcpy(data + cpLen, secondBuff, secondCpLen); 197 | endReadBuff(NULL, 0, secondBuff, secondCpLen); 198 | cpLen += secondCpLen; 199 | } 200 | 201 | return cpLen; 202 | } 203 | 204 | inline unsigned int getDataSize() const 205 | { 206 | // 一次性拷贝读写索引,防止读写线程并发修改发生变化而导致错误 207 | unsigned int rdIdx = readIdx; 208 | unsigned int wtIdx = writeIdx; 209 | return (rdIdx <= wtIdx) ? (wtIdx - rdIdx) : (buffSize - rdIdx + wtIdx); 210 | } 211 | 212 | inline unsigned int getFreeSize() const 213 | { 214 | // 一次性拷贝读写索引,防止读写线程并发修改发生变化而导致错误 215 | unsigned int rdIdx = readIdx; 216 | unsigned int wtIdx = writeIdx; 217 | 218 | // 注意:buffSize == wtIdx && rdIdx 为 0 的情况 219 | unsigned int freeSize = (wtIdx < rdIdx) ? (rdIdx - wtIdx) : (buffSize - wtIdx + rdIdx); 220 | return (freeSize > 0) ? (freeSize - 1) : 0; // 留出一个字节的空位,用于判断队列是否满了 221 | } 222 | 223 | inline bool isEmpty() const 224 | { 225 | // 一次性拷贝读写索引,防止读写线程并发修改发生变化而导致错误 226 | unsigned int rdIdx = readIdx; 227 | unsigned int wtIdx = writeIdx; 228 | return (rdIdx == wtIdx) || (wtIdx == 0 && rdIdx == buffSize); 229 | } 230 | 231 | inline bool isFull() const 232 | { 233 | return getFreeSize() == 0; 234 | } 235 | }; 236 | 237 | } 238 | 239 | #endif // CSINGLEW_SINGLER_BUFFER_H 240 | -------------------------------------------------------------------------------- /common/base_lib/CThread.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.21 4 | * description : 线程管理API封装 5 | */ 6 | 7 | #include 8 | #include "CThread.h" 9 | #include "MacroDefine.h" 10 | 11 | 12 | namespace NCommon 13 | { 14 | 15 | void* runThreadFunc(void* pObj) 16 | { 17 | CThread* pThread = (CThread*)pObj; 18 | pThread->run(); 19 | return NULL; 20 | } 21 | 22 | 23 | CThread::CThread() : m_pId(0) 24 | { 25 | } 26 | 27 | CThread::~CThread() 28 | { 29 | m_pId = 0; 30 | } 31 | 32 | 33 | int CThread::detach(pthread_t pid) 34 | { 35 | int rc = pthread_detach(pid); 36 | if (rc != 0) 37 | { 38 | ReleaseErrorLog("call pthread_detach pid = %ld, error = %d, info = %s", pid, rc, strerror(rc)); // 运行日志 39 | } 40 | return rc; 41 | } 42 | 43 | int CThread::join(pthread_t pid, void** retVal) 44 | { 45 | int rc = pthread_join(pid, retVal); 46 | if (rc != 0) 47 | { 48 | ReleaseErrorLog("call pthread_join pid = %ld, error = %d, info = %s", pid, rc, strerror(rc)); // 运行日志 49 | } 50 | return rc; 51 | } 52 | 53 | int CThread::cancel(pthread_t pid) 54 | { 55 | int rc = pthread_cancel(pid); 56 | if (rc != 0) 57 | { 58 | ReleaseErrorLog("call pthread_cancel pid = %ld, error = %d, info = %s", pid, rc, strerror(rc)); // 运行日志 59 | } 60 | return rc; 61 | } 62 | 63 | 64 | int CThread::start() 65 | { 66 | int rc = pthread_create(&m_pId, NULL, runThreadFunc, (void*)this); 67 | if (rc != 0) 68 | { 69 | ReleaseErrorLog("call pthread_create error = %d, info = %s", rc, strerror(rc)); // 运行日志 70 | } 71 | return rc; 72 | } 73 | 74 | int CThread::yield() 75 | { 76 | return pthread_yield(); 77 | } 78 | 79 | void CThread::stop() 80 | { 81 | pthread_exit(NULL); 82 | } 83 | 84 | // 线程主动分离自己,必须在run函数调用才能生效 85 | int CThread::detach() 86 | { 87 | int rc = pthread_detach(pthread_self()); 88 | if (rc != 0) 89 | { 90 | ReleaseErrorLog("call pthread_detach error = %d, info = %s", rc, strerror(rc)); // 运行日志 91 | } 92 | return rc; 93 | } 94 | 95 | pthread_t CThread::getId() 96 | { 97 | return m_pId; 98 | } 99 | 100 | const char* CThread::getName() 101 | { 102 | return ""; 103 | } 104 | 105 | void CThread::run() 106 | { 107 | } 108 | 109 | } 110 | 111 | -------------------------------------------------------------------------------- /common/base_lib/CThread.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.21 4 | * description : 线程管理API封装 5 | */ 6 | 7 | #ifndef CTHREAD_H 8 | #define CTHREAD_H 9 | 10 | #include 11 | 12 | 13 | namespace NCommon 14 | { 15 | 16 | class CThread 17 | { 18 | public: 19 | CThread(); 20 | virtual ~CThread(); 21 | 22 | public: 23 | // 线程管理api 24 | static int detach(pthread_t pid); // 分离线程 25 | static int join(pthread_t pid, void** retVal); // 等待线程结束 26 | static int cancel(pthread_t pid); // 取消停止线程 27 | 28 | 29 | public: 30 | int start(); // 创建线程并执行run函数调用 31 | 32 | // 以下函数只能在线程运行函数run内调用 33 | int yield(); // 挂起线程,只能在线程内主动调用 34 | int detach(); // 线程主动分离自己,必须在run函数调用才能生效 35 | void stop(); // 停止线程,只能在线程内主动调用 36 | 37 | public: 38 | pthread_t getId(); // 线程id 39 | virtual const char* getName(); // 线程名称 40 | 41 | private: 42 | // 禁止拷贝、赋值 43 | CThread(const CThread&); 44 | CThread& operator =(const CThread&); 45 | 46 | private: 47 | virtual void run(); // 线程实现者重写run 48 | 49 | private: 50 | pthread_t m_pId; 51 | 52 | 53 | friend void* runThreadFunc(void* pObj); 54 | }; 55 | 56 | } 57 | 58 | #endif // CTHREAD_H 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /common/base_lib/CTimer.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.09 4 | * description : 定时器 5 | */ 6 | 7 | #ifndef __CTIMER_H__ 8 | #define __CTIMER_H__ 9 | 10 | #include 11 | #include 12 | #include "CThread.h" 13 | 14 | namespace NCommon 15 | { 16 | 17 | class CMutex; 18 | class CMemManager; 19 | 20 | class CTimerI 21 | { 22 | public: 23 | virtual bool OnTimer(unsigned int timerId, void *pParam, unsigned int remainCount) = 0; 24 | }; 25 | 26 | class STimerInfo 27 | { 28 | public: 29 | unsigned int timerId; 30 | CTimerI * pTimerI; //回调类指针 31 | unsigned int runCounts; // -1代表无限次 32 | unsigned int timeGap; //执行时间间隔,单位ms 33 | void * pParam; 34 | long long lastExeTimestamp; //上次的执行时间戳,单位ms 35 | 36 | public: 37 | STimerInfo() 38 | { 39 | timerId = 0; 40 | pTimerI = (CTimerI *)0; 41 | runCounts = 1; 42 | timeGap = 100; 43 | pParam = (void *)0; 44 | lastExeTimestamp = 0; 45 | } 46 | }; 47 | 48 | class CTimer : public CThread 49 | { 50 | public: 51 | CTimer(); 52 | ~CTimer(); 53 | 54 | int startTimer(); 55 | 56 | //设置定时器,时间单位ms,最小粒度100ms,runCounts 为-1时代表无限次,返回值 timerId 非0 57 | unsigned int setTimer(unsigned int timeGap, CTimerI* pTimerI, void *pParam = (void *)0, unsigned int runCounts = 1); 58 | void killTimer(unsigned int timerId); 59 | void clearAllTimer(); 60 | int stopTimer(); 61 | 62 | private: 63 | // 禁止拷贝、赋值 64 | CTimer(const CTimer&); 65 | CTimer& operator =(const CTimer&); 66 | virtual void run(); // 线程实现者重写run 67 | int insertTimer(STimerInfo *pTimerInfo); 68 | int eraseTimer(unsigned int index); 69 | 70 | inline int cmpTimerInfo(STimerInfo *pTimerInfo_1, STimerInfo *pTimerInfo_2) 71 | { 72 | long long timeVal1 = pTimerInfo_1->lastExeTimestamp + pTimerInfo_1->timeGap; 73 | long long timeVal2 = pTimerInfo_2->lastExeTimestamp + pTimerInfo_2->timeGap; 74 | return (timeVal1 < timeVal2) ? -1 : 1; 75 | // return int(pTimerInfo_1->lastExeTimestamp + pTimerInfo_1->timeGap - pTimerInfo_2->lastExeTimestamp - pTimerInfo_2->timeGap); 76 | } 77 | 78 | inline void swapTimerInfo(std::vector &m_vTimer, unsigned int indexA, unsigned int indexB) 79 | { 80 | STimerInfo *tmp = m_vTimer[indexA]; 81 | m_vTimer[indexA] = m_vTimer[indexB]; 82 | m_vTimer[indexB] = tmp; 83 | } 84 | 85 | private: 86 | unsigned int m_curTimerId; 87 | CMemManager *m_pMemManager; 88 | CMutex *m_pMutex; 89 | std::unordered_map m_umapKillTimer; 90 | std::vector m_vTimer; 91 | volatile bool m_isRun; 92 | }; 93 | 94 | } 95 | 96 | #endif // CTIMER_H 97 | 98 | 99 | -------------------------------------------------------------------------------- /common/base_lib/CUUId.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.19 4 | * description : UUID唯一生成管理实现 5 | */ 6 | 7 | #include 8 | 9 | #include "CUUId.h" 10 | #include "MacroDefine.h" 11 | #include "ErrorCode.h" 12 | 13 | 14 | using namespace NErrorCode; 15 | 16 | namespace NCommon 17 | { 18 | 19 | unsigned short CUUId::s_serverIdx = 0; 20 | unsigned short CUUId::s_len = 0; 21 | unsigned int* CUUId::s_type2Idx = NULL; 22 | 23 | 24 | int CUUId::init(unsigned short serverIdx, unsigned int type2Idx[], unsigned short len) 25 | { 26 | if (serverIdx < 1 || type2Idx == NULL || len < 1) 27 | { 28 | return InvalidParam; 29 | } 30 | 31 | NEW_ARRAY(s_type2Idx, unsigned int[len]); 32 | if (s_type2Idx == NULL) 33 | { 34 | return NoMemory; 35 | } 36 | 37 | s_serverIdx = serverIdx; 38 | s_len = len; 39 | memcpy(s_type2Idx, type2Idx, sizeof(unsigned int) * len); 40 | 41 | return Success; 42 | } 43 | 44 | void CUUId::unInit() 45 | { 46 | s_serverIdx = 0; 47 | s_len = 0; 48 | DELETE_ARRAY(s_type2Idx); 49 | } 50 | 51 | uuid_type CUUId::generateId(IdTypeVal t_val) 52 | { 53 | static uuid_type id = 0; // 先简单实现 54 | ++id; 55 | return id; 56 | } 57 | 58 | uuid_type CUUId::generateUserId() 59 | { 60 | return generateId(user); 61 | } 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /common/base_lib/CUUId.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.19 4 | * description : UUID唯一生成管理实现 5 | */ 6 | 7 | #ifndef CUUID_H 8 | #define CUUID_H 9 | 10 | #include "Type.h" 11 | 12 | 13 | namespace NCommon 14 | { 15 | 16 | // UUID 类型字段,各个类型值定义 17 | enum IdTypeVal 18 | { 19 | user = 0, // 用户类型 20 | }; 21 | 22 | 23 | // UUID 工具类 24 | class CUUId 25 | { 26 | public: 27 | static int init(unsigned short serverIdx, unsigned int type2Idx[], unsigned short len); 28 | static void unInit(); 29 | 30 | public: 31 | static uuid_type generateId(IdTypeVal t_val); 32 | static uuid_type generateUserId(); 33 | 34 | private: 35 | // 禁止创建CUUId对象 36 | CUUId(); 37 | ~CUUId(); 38 | CUUId(const CUUId&); 39 | CUUId& operator =(const CUUId&); 40 | 41 | private: 42 | static unsigned short s_serverIdx; 43 | static unsigned short s_len; 44 | static unsigned int* s_type2Idx; 45 | }; 46 | 47 | } 48 | 49 | #endif // CUUID_H 50 | -------------------------------------------------------------------------------- /common/base_lib/Constant.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.15 4 | * description : 各种常量定义,配置值等等 5 | */ 6 | 7 | #ifndef CONSTANT_H 8 | #define CONSTANT_H 9 | 10 | 11 | // 技术性常量配置放到这里 12 | // 非技术性常量放到外面的配置文件里 13 | namespace NCommon 14 | { 15 | static const int CfgKeyValueLen = 128; // 配置文件名值对字符串的最大长度 16 | static const int MaxFullLen = 2048; // 支持的最大全路径文件名长度 17 | static const int MaxLogBuffLen = 1024 * 128; // 支持一次写入的最大日志长度 18 | static const int WriteErrTime = 5; // 连续写日志文件多少次失败后,重新关闭&打开文件 19 | static const int TryTimes = 10; // 连续尝试打开多少次日志文件失败后,关闭日志功能 20 | static const int MinConnectPort = 2000; // socket主动建立连接的最小端口号,防止和系统端口号冲突 21 | } 22 | 23 | 24 | #endif // CONSTANT_H 25 | -------------------------------------------------------------------------------- /common/base_lib/ErrorCode.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.15 4 | * description : 各个模块,各种函数,返回码、错误码定义,统一管理 5 | */ 6 | 7 | #ifndef ERROR_CODE_H 8 | #define ERROR_CODE_H 9 | 10 | 11 | namespace NErrorCode 12 | { 13 | 14 | // redis 错误码范围[-101 -- -200] 15 | // 注意:封装的 redis api 把错误码作为数据长度返回了,因此错误码只能定义为负数表示错误 16 | enum ERedis 17 | { 18 | NormalError = -101, // redis常规错误,说明用的不对 19 | NetError = -102, // 网络连接错误 20 | SpaceNotEnough = -103, // 存储空间不够 21 | }; 22 | 23 | 24 | // 公共模块 错误码范围[0---100] 25 | enum ECommon 26 | { 27 | Success = 0, // 调用成功 28 | 29 | InvalidParam = 1, // 无效参数 30 | NoMemory = 2, // new 失败,没内存了 31 | 32 | QueueFull = 3, // 消息队列满了 33 | SystemCallErr = 4, // 系统调用失败 34 | }; 35 | 36 | 37 | // 共享内存模块 错误码范围[101---120] 38 | enum EShm 39 | { 40 | OpenKeyFileFailed = 101, // 打开共享内存key文件失败 41 | LockKeyFileFailed = 102, // 锁定共享内存key文件失败 42 | CreateKeyFileFailed = 103, // 创建共享内存key文件失败 43 | ShmProcIdEqual = 104, // 共享内存通信两端逻辑进程号相同 44 | CreateShmFailed = 105, // 创建共享内存失败 45 | UponShmFailed = 106, // 映射共享内存失败 46 | ShmNotMateId = 107, // 共享内存不匹配通信进程逻辑ID 47 | OffShmFailed = 108, // 关闭共享内存失败 48 | PkgQueueFull = 109, // 数据包队列满了 49 | PkgQueueEmpty = 110, // 数据包队列空了 50 | PkgSuperLarge = 111, // 用户数据包过大 51 | ReadPkgConflict = 112, // 读取数据包数据发生冲突了 52 | RWInvalidParam = 113, // 读写数据包传递的参数无效 53 | ReadPkgBuffSmall = 114, // 读写数据包的用户空间不足 54 | UnLockKeyFileFailed = 115, // 解锁共享内存key文件失败 55 | }; 56 | 57 | 58 | // 网络连接模块 错误码范围[121---150] 59 | enum EConnect 60 | { 61 | CreateSocketFailed = 121, // 创建socket失败 62 | CloseSocketFailed = 122, // 关闭socket失败 63 | InValidIp = 123, // 无效ip地址 64 | BindIpPortFailed = 124, // 绑定ip、端口失败 65 | ListenConnectFailed = 125, // 启动监听连接失败 66 | ConnectIpPortFailed = 126, // 连接失败 67 | SetLingerFailed = 127, // 选项设置失败 68 | SetRcvBuffFailed = 128, // 选项设置失败 69 | SetSndBuffFailed = 129, // 选项设置失败 70 | SetReuseAddrFailed = 130, // 选项设置失败 71 | SetNagleFailed = 131, // 选项设置失败 72 | SetNonBlockFailed = 132, // 选项设置失败 73 | AcceptConnectFailed = 133, // 建立连接失败 74 | }; 75 | 76 | 77 | // 连接管理服务 错误码范围[151---170] 78 | enum EConnServer 79 | { 80 | CreateMemPoolFailed = 151, // 创建内存池失败 81 | CreateEPollFailed = 152, // 创建epoll模型失败 82 | AddEPollListenerFailed = 153, // 增加监听者失败 83 | RemoveEPollListenerFailed = 154, // 删除监听者失败 84 | ModifyEPollListenerFailed = 155, // 修改监听事件失败 85 | ListenConnectException = 156, // 监听连接异常 86 | }; 87 | 88 | 89 | // 服务消息通信中间件 错误码范围[171---180] 90 | enum ESrvMsgComm 91 | { 92 | InitSharedMutexError = 171, // 初始化共享内存共享锁失败 93 | SrvMsgCommCfgError = 172, // SrvMsgComm 段配置错误 94 | ServiceIDCfgError = 173, // ServiceID 段配置错误 95 | NetConnectCfgError = 174, // NetConnect 段配置错误 96 | NotFoundService = 175, // 没有找到对应的服务 97 | SharedMemoryDataError = 176, // 共享内存数据错误 98 | GetSharedMemoryBlockError = 177, // 获取共享内存块错误 99 | CfgInvalidIPError = 178, // 配置了无效的IP 100 | NodePortCfgError = 179, // NodePort 段配置错误 101 | GetSrvFileKeyError = 180, // 获取服务对应的关键文件失败 102 | NotServiceMsg = 181, // 服务当前没有收到消息 103 | }; 104 | 105 | 106 | // 服务框架 错误码范围[191---210] 107 | enum ESrvFrame 108 | { 109 | NotRegisterService = 191, // 未注册服务 110 | LargeMessage = 192, // 超大消息包不支持 111 | LargeUserData = 193, // 超大用户数据不支持 112 | ServiceIPError = 194, // 配置了无效的IP 113 | ServicePortError = 195, // Port配置错误 114 | SrvConnectCfgError = 196, // 服务连接配置项错误 115 | NoSupportConnectClient = 197, // 不支持客户端连接 116 | NoFoundClientConnect = 198, // 找不到用户名对应的连接 117 | NoFoundConnectProxy = 199, // 找不到用户名对应的连接代理 118 | NetClientContextError = 200, // 网络连接客户端上下文错误 119 | NoFoundProtocolHandler = 201, // 找不到对应的协议处理函数 120 | NoLogicHandle = 202, // 无处理逻辑处理 121 | LargeAsyncDataFlag = 203, // 超大异步数据标识不支持 122 | }; 123 | 124 | 125 | // MySql操作 错误码范围[211---230] 126 | enum EMySqlOpt 127 | { 128 | InitMySqlLibError = 211, // 初始化MySql库失败错误 129 | ConnectMySqlError = 212, // 连接MySql错误 130 | DoSqlCmmError = 213, // 执行sql命令出错 131 | GetSqlAllResultError = 214, // 一次性获取所有查询结果集出错 132 | GetSqlResultError = 215, // 获取单个查询结果集出错 133 | DoPreStmtCmmError = 216, // 执行预处理sql命令出错 134 | }; 135 | 136 | 137 | // HTTP基础库错误码范围[231 -- 240] 138 | enum EHttpBase 139 | { 140 | HeaderDataError = 231, // http消息头错误 141 | BodyDataError = 232, // http消息体错误 142 | IncompleteBodyData = 233, // 不完整的http消息体 143 | }; 144 | 145 | 146 | }; 147 | 148 | 149 | #endif // ERROR_CODE_H 150 | -------------------------------------------------------------------------------- /common/base_lib/Function.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.3.9 4 | * description : 通用函数 5 | */ 6 | 7 | #ifndef __FUNCTION_H__ 8 | #define __FUNCTION_H__ 9 | 10 | #include 11 | #include 12 | 13 | 14 | namespace NCommon 15 | { 16 | int b2str(const char *buf, const int bufLen, char *str, const int strLen, bool capital = true); //将buf转为16进制字串 17 | bool strIsDigit(const char *str, const int strLen = 0); //判断字串是否为纯数字 18 | bool strIsAlpha(const char *str, const int strLen = 0); //判断字串是否为纯字母 19 | bool strIsAlnum(const char *str, const int strLen = 0); //判断字串是否为数字或字母 20 | bool strIsAlnumOrNonAscii(const char *str, const int strLen = 0); //判断字串是否为数字或字母或非ascii(比如汉字等) 21 | bool strIsSqlchar(const char *str, const int strLen = 0); //判断字串是否为ascii内sql合法字串 22 | bool strIsSqlcharOrNonAscii(const char *str, const int strLen = 0); //判断字串是否为ascii内sql合法字串或非ascii(比如汉字等) 23 | bool strIsUpperHex(const char *str, const int strLen = 0); //判断字串是否为大写的16进制字串(0~9 或 A~F) 24 | bool strIsDate(const char *str, const int strLen = 0); //判断字串是否为 日期格式 25 | unsigned int strToHashValue(const char *str, const int strLen = 0); //将一个字符串(或2进制buf)转为uint32类型并返回 26 | unsigned int strToHashValueCaseInsensitive(const char *str, const int strLen = 0); //将一个字符串(不分区大小写)转为uint32类型并返回 27 | unsigned int genChecksum(const char* buf, const int bufLen); // 计算二进制内容的checksum 28 | void simpleEncryptDecrypt(char* buf, const int bufLen); // 简单的对称加密算法, buf即是输入,也是输出 29 | bool aesEncrypt(char* buf, int bufLen, const char key[AES_BLOCK_SIZE]); // aes加密,bufLen为16的倍数 30 | bool aesDecrypt(char* buf, int bufLen, const char key[AES_BLOCK_SIZE]); // aes解密,bufLen为16的倍数 31 | uint64_t getMilliSecsTimestamp(); // 当前时间毫秒数 32 | char* filterInvalidChars(char* charString); // 过滤无效的不可见字符 33 | bool isValidIPv4AddressFormat(const char* ipStr); // 判断是否为有效的IPv4地址格式 34 | } 35 | 36 | #endif // __FUNCTION_H__ 37 | -------------------------------------------------------------------------------- /common/base_lib/MacroDefine.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.15 4 | * description : 各种宏定义 5 | */ 6 | 7 | #ifndef MACRO_DEFINE_H 8 | #define MACRO_DEFINE_H 9 | 10 | #include "CLogger.h" 11 | #include "CMemMonitor.h" 12 | 13 | 14 | #ifndef NULL 15 | #define NULL 0 16 | #endif 17 | 18 | #ifndef __FILE__ 19 | #define __FILE__ "" 20 | #endif 21 | 22 | #ifndef __LINE__ 23 | #define __LINE__ 0 24 | #endif 25 | 26 | 27 | // new & delete 宏定义,防止内存操作失败抛出异常 28 | #define NEW(pointer, ClassType) \ 29 | try \ 30 | { \ 31 | pointer = new ClassType; \ 32 | NCommon::CMemMonitor::getInstance().newMemInfo(pointer, __FILE__, __LINE__, sizeof(ClassType)); \ 33 | } \ 34 | catch(...) \ 35 | { \ 36 | pointer = NULL; \ 37 | } 38 | 39 | #define NEW0(pointer, ClassType) \ 40 | try \ 41 | { \ 42 | pointer = new ClassType(); \ 43 | NCommon::CMemMonitor::getInstance().newMemInfo(pointer, __FILE__, __LINE__, sizeof(ClassType)); \ 44 | } \ 45 | catch(...) \ 46 | { \ 47 | pointer = NULL; \ 48 | } 49 | 50 | 51 | #define DELETE(pointer) \ 52 | try \ 53 | { \ 54 | delete pointer; \ 55 | NCommon::CMemMonitor::getInstance().deleteMemInfo(pointer); \ 56 | pointer = NULL; \ 57 | } \ 58 | catch(...) \ 59 | { \ 60 | pointer = NULL; \ 61 | } 62 | 63 | 64 | #define NEW_ARRAY(pointer, ClassArray) \ 65 | try \ 66 | { \ 67 | pointer = new ClassArray; \ 68 | NCommon::CMemMonitor::getInstance().newMemInfo(pointer, __FILE__, __LINE__, sizeof(ClassArray)); \ 69 | } \ 70 | catch(...) \ 71 | { \ 72 | pointer = NULL; \ 73 | } 74 | 75 | 76 | #define DELETE_ARRAY(pointer) \ 77 | try \ 78 | { \ 79 | delete [] pointer; \ 80 | NCommon::CMemMonitor::getInstance().deleteMemInfo(pointer); \ 81 | pointer = NULL; \ 82 | } \ 83 | catch(...) \ 84 | { \ 85 | pointer = NULL; \ 86 | } 87 | 88 | 89 | 90 | // 各种类型的日志宏 91 | #ifdef DEBUG // debug log 日志开关 92 | #define SetDebugLogOutput(value) CLogger::getDebugLogger().setOutput(value) 93 | #define DebugLog(level, format, args...) CLogger::getDebugLogger().writeFile(__FILE__, __LINE__, level, format, ##args) 94 | #else 95 | #define SetDebugLogOutput(value) 96 | #define DebugLog(level, format, args...) 97 | #endif 98 | 99 | /* 调试日志 100 | 日志级别开关配置说明: 101 | enum LogLevel { 102 | Info = 2, 103 | Warn = 3, 104 | Error = 4, 105 | Business = 5, 106 | Dev = 6, 107 | Test = 7, 108 | Product = 8, 109 | }; 110 | 111 | 各服务配置文件 common.cfg 里的 [Logger] 配置项: 112 | [Logger] 113 | WriteDebugLog = 0 // 0值关闭日志 114 | WriteDebugLog = 1 // 1值打开所有级别的日志 115 | 116 | // 打开相关级别的日志,各级别对应的值 LogLevel 任意组合,如下配置: 117 | WriteDebugLog = 2 // 只打开 Info 级别日志 118 | WriteDebugLog = 45 // 只打开 Error、Business 级别日志 119 | WriteDebugLog = 34 // 只打开 Warn、Error 级别日志 120 | WriteDebugLog = 478 // 只打开 Error、Test、Product 级别日志 121 | */ 122 | #define DebugInfoLog(format, args...) DebugLog(LogLevel::Info, format, ##args) 123 | #define DebugWarnLog(format, args...) DebugLog(LogLevel::Warn, format, ##args) 124 | #define DebugErrorLog(format, args...) DebugLog(LogLevel::Error, format, ##args) 125 | #define DebugBusinessLog(format, args...) DebugLog(LogLevel::Business, format, ##args) 126 | #define DebugDevLog(format, args...) DebugLog(LogLevel::Dev, format, ##args) 127 | #define DebugTestLog(format, args...) DebugLog(LogLevel::Test, format, ##args) 128 | #define DebugProductLog(format, args...) DebugLog(LogLevel::Product, format, ##args) 129 | 130 | 131 | // 运行日志 132 | #define SetReleaseLogOutput(value) CLogger::getReleaseLogger().setOutput(value) 133 | #define ReleaseLog(level, format, args...) CLogger::getReleaseLogger().writeFile(NULL, 0, level, format, ##args) 134 | #define ReleaseInfoLog(format, args...) ReleaseLog(LogLevel::Info, format, ##args) 135 | #define ReleaseWarnLog(format, args...) ReleaseLog(LogLevel::Warn, format, ##args) 136 | #define ReleaseErrorLog(format, args...) ReleaseLog(LogLevel::Error, format, ##args) 137 | 138 | 139 | // 操作日志 140 | #define SetOptLogOutput(value) CLogger::getOptLogger().setOutput(value) 141 | #define OptLog(level, format, args...) CLogger::getOptLogger().writeFile(NULL, 0, level, format, ##args) 142 | #define OptInfoLog(format, args...) OptLog(LogLevel::Info, format, ##args) 143 | #define OptWarnLog(format, args...) OptLog(LogLevel::Warn, format, ##args) 144 | #define OptErrorLog(format, args...) OptLog(LogLevel::Error, format, ##args) 145 | 146 | 147 | 148 | // 位数组定义 149 | #ifndef CHAR_BIT 150 | #define CHAR_BIT (8) 151 | #endif 152 | 153 | #define BIT_MASK(idx) (1 << ((idx) % CHAR_BIT)) 154 | #define BIT_IDX(idx) ((idx) / CHAR_BIT) 155 | #define BIT_LEN(bn) (((bn) + (CHAR_BIT - 1)) / CHAR_BIT) 156 | #define BIT_SET(ba, idx) ((ba)[BIT_IDX(idx)] |= BIT_MASK(idx)) 157 | #define BIT_CLE(ba, idx) ((ba)[BIT_IDX(idx)] &= (~BIT_MASK(idx))) 158 | #define BIT_TST(ba, idx) ((ba)[BIT_IDX(idx)] & BIT_MASK(idx)) 159 | 160 | 161 | 162 | // 禁止默认构造函数 163 | #define DISABLE_CONSTRUCTION(CLASS_NAME) \ 164 | private: \ 165 | CLASS_NAME() 166 | 167 | // 禁止析构函数 168 | #define DISABLE_DECONSTRUCTION(CLASS_NAME) \ 169 | private: \ 170 | ~CLASS_NAME() 171 | 172 | // 禁止拷贝赋值类函数 173 | #define DISABLE_COPY_ASSIGN(CLASS_NAME) \ 174 | private: \ 175 | CLASS_NAME(const CLASS_NAME&); \ 176 | CLASS_NAME& operator =(const CLASS_NAME&) 177 | 178 | // 禁止构造&拷贝&赋值类函数 179 | #define DISABLE_CONSTRUCTION_ASSIGN(CLASS_NAME) \ 180 | DISABLE_CONSTRUCTION(CLASS_NAME); \ 181 | DISABLE_COPY_ASSIGN(CLASS_NAME) 182 | 183 | // 禁止类基本函数 184 | #define DISABLE_CLASS_BASE_FUNC(CLASS_NAME) \ 185 | DISABLE_CONSTRUCTION_ASSIGN(CLASS_NAME); \ 186 | DISABLE_DECONSTRUCTION(CLASS_NAME) 187 | 188 | 189 | 190 | #endif // MACRO_DEFINE_H 191 | 192 | -------------------------------------------------------------------------------- /common/base_lib/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -static -I/usr/local/include -I../../../import/third_party/include -g -Wall -o2 -std=c++0x 2 | CFLAGS += #调试日志开关,编译运行版本的时候注释掉该选项 3 | CC=g++ 4 | SRC=$(wildcard *.cpp) 5 | OBJ=$(addprefix ./, $(addsuffix .o, $(basename $(SRC)))) 6 | TARGET=../../../lib/libbase.a 7 | 8 | all: $(TARGET) 9 | 10 | $(TARGET): $(OBJ) 11 | $(AR) -rcs $@ $^ 12 | rm -f $(OBJ) 13 | 14 | %.o: %.c 15 | $(CC) $(CFLAGS) -o $@ -c $< 16 | 17 | %.o: %.cpp 18 | $(CC) $(CFLAGS) -o $@ -c $< 19 | 20 | clean: 21 | rm -f $(TARGET) $(OBJ) 22 | -------------------------------------------------------------------------------- /common/base_lib/Type.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.10.29 4 | * description : 各种类型定义 5 | */ 6 | 7 | #ifndef TYPE_H 8 | #define TYPE_H 9 | 10 | #include 11 | 12 | 13 | // 网络码流传输的类型 14 | typedef char char8_t; 15 | typedef short short16_t; 16 | typedef int int32_t; 17 | typedef long long long64_t; 18 | typedef float float32_t; 19 | typedef double double64_t; 20 | 21 | typedef unsigned char uchar8_t; 22 | typedef unsigned short ushort16_t; 23 | typedef unsigned int uint32_t; 24 | typedef unsigned long long ulong64_t; 25 | 26 | 27 | typedef ulong64_t uuid_type; // 唯一用户ID类型 28 | 29 | static const int StrIPLen = 32; 30 | typedef char strIP_t[StrIPLen]; // IP 类型 31 | 32 | static const int StrIntLen = 32; 33 | typedef char strInt_t[StrIntLen]; // 整型 34 | 35 | 36 | namespace NCommon 37 | { 38 | 39 | static inline char* intValueToChars(const int val, strInt_t str) 40 | { 41 | snprintf(str, StrIntLen - 1, "%d", val); 42 | return str; 43 | } 44 | 45 | 46 | // 节点ID 47 | union NodeID 48 | { 49 | uuid_type id; 50 | struct IpPort 51 | { 52 | unsigned int ip; 53 | unsigned int port; 54 | } ipPort; 55 | }; 56 | 57 | 58 | // 共享内存相关数据类型 59 | // 数据包类型 60 | enum PkgFlag 61 | { 62 | USER_DATA = 1, // 用户数据 63 | BUFF_END = 2, // 数据包缓冲区已到尾部 64 | }; 65 | 66 | // 数据包头 67 | struct PkgHeader 68 | { 69 | int len; // 数据包长度 70 | unsigned char flag; // 数据包标识符 71 | unsigned char cmd; // 控制信息,目前为0 72 | unsigned char ver; // 版本号,目前为0 73 | unsigned char res; // 保留字段,目前为0 74 | }; 75 | 76 | // 统计数据信息 77 | struct PkgRecord 78 | { 79 | unsigned int writeCount; // 写入的数据包总个数 80 | unsigned int writeSize; // 写入的数据包总长度 81 | 82 | unsigned int readCount; // 读取的数据包总个数 83 | unsigned int readSize; // 读取的数据包总长度 84 | }; 85 | 86 | // 数据包队列 87 | struct PkgQueue 88 | { 89 | int size; 90 | volatile int write; 91 | volatile int read; 92 | PkgRecord record; 93 | }; 94 | 95 | } 96 | 97 | 98 | #endif // TYPE_H 99 | -------------------------------------------------------------------------------- /common/base_lib/readme: -------------------------------------------------------------------------------- 1 | base lib code, 2 | 实现配置文件读写、日志、多线程、多进程、锁、对象引用计数、内存池、免锁消息队列、免锁数据缓冲区、进程信号、共享内存、定时器等等基础功能组件代码。 3 | -------------------------------------------------------------------------------- /common/base_lib/xmlConfig.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.05.08 4 | * description : xml解析生成代码API 5 | */ 6 | 7 | #ifndef _XML_CONFIG_H_ 8 | #define _XML_CONFIG_H_ 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | using namespace std; 18 | using namespace xercesc; 19 | 20 | namespace NXmlConfig 21 | { 22 | 23 | typedef vector DomNodeArray; 24 | 25 | class IXmlConfigBase; 26 | 27 | class ReadXml 28 | { 29 | public: 30 | ReadXml(); 31 | ~ReadXml(); 32 | 33 | public: 34 | void setConfig(const char* xmlConfigFile, IXmlConfigBase& configVal); 35 | 36 | public: 37 | DOMElement* getDocumentRoot(const char* xmlConfigFile); 38 | 39 | 40 | private: 41 | XercesDOMParser* m_DOMXmlParser; 42 | }; 43 | 44 | 45 | class IXmlConfigBase 46 | { 47 | public: 48 | bool isSetConfigValueSuccess() const { return __isSetConfigValueSuccess__; }; 49 | 50 | public: 51 | IXmlConfigBase() : __isSetConfigValueSuccess__(false) {}; 52 | virtual ~IXmlConfigBase() {}; 53 | virtual void set(DOMNode* parent) = 0; 54 | 55 | private: 56 | bool __isSetConfigValueSuccess__; 57 | 58 | friend class ReadXml; 59 | }; 60 | 61 | 62 | class CXmlConfig 63 | { 64 | public: 65 | static void setConfigValue(const char* xmlConfigFile, IXmlConfigBase& configVal); 66 | 67 | public: 68 | static void getNode(DOMNode* parentNode, DomNodeArray& domNodeArray, const string& parentName, const string& nodeName, const string& typeValue = "struct"); 69 | static void getNode(DOMNode* parentNode, const string& typeName, const string& typeValue, DomNodeArray& domNodeArray); 70 | static string getValue(DOMNode* parentNode, const string& itemName); 71 | static string getKey(DOMNode* parentNode, const char* keyName); 72 | 73 | public: 74 | static void getChildNode(DOMNode* parentNode, DomNodeArray& domNodeArray, const string& parentName, const string& nodeName, const string& typeValue); 75 | static void getChildNode(DOMNode* parentNode, const string& typeName, const string& typeValue, DomNodeArray& domNodeArray); 76 | static void charArrayToString(const XMLCh* xmlChar, string& value); 77 | static void getAttribute(DOMNode* node, const char* name, string& value); 78 | 79 | public: 80 | static int stringToInt(const string str); 81 | static long stringToLong(const string str); 82 | static double stringToDouble(const string str); 83 | 84 | private: 85 | CXmlConfig(); 86 | }; 87 | 88 | } 89 | 90 | 91 | #endif // _XML_CONFIG_H_ 92 | 93 | -------------------------------------------------------------------------------- /common/connect_lib/CClient.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.12.01 4 | * description : 网络终端发起连接 5 | */ 6 | 7 | #include "CClient.h" 8 | 9 | namespace NConnect 10 | { 11 | 12 | CClient::CClient() 13 | { 14 | } 15 | 16 | CClient::~CClient() 17 | { 18 | } 19 | 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /common/connect_lib/CClient.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.12.01 4 | * description : 网络终端发起连接 5 | */ 6 | 7 | #ifndef CCLIENT_H 8 | #define CCLIENT_H 9 | 10 | namespace NConnect 11 | { 12 | 13 | class CClient 14 | { 15 | public: 16 | CClient(); 17 | ~CClient(); 18 | 19 | }; 20 | 21 | } 22 | 23 | #endif // CCLIENT_H 24 | -------------------------------------------------------------------------------- /common/connect_lib/CConnectManager.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.12.05 4 | * description : 网络连接管理 5 | */ 6 | 7 | #ifndef CCONNECT_MANAGER_H 8 | #define CCONNECT_MANAGER_H 9 | 10 | #include 11 | #include "CTcpConnect.h" 12 | #include "CEpoll.h" 13 | #include "base/CMemManager.h" 14 | #include "base/MacroDefine.h" 15 | #include "NetType.h" 16 | 17 | 18 | namespace NConnect 19 | { 20 | 21 | // 对已经建立、初始化好了的连接的操作 22 | enum ConnectOpt 23 | { 24 | EAddToQueue = 1, // 加入消息队列,可以从该连接读取数据 25 | ENeedReadData = 2, // 该连接检测到有数据可读,应用层需要从该连接读取数据 26 | }; 27 | 28 | typedef std::unordered_map NodeIdToTimeSecs; 29 | typedef std::unordered_map IdToConnect; 30 | 31 | class ILogicHandler; 32 | 33 | struct ServerCfgData 34 | { 35 | unsigned int listenMemCache; // 连接内存池内存块个数 36 | 37 | unsigned int count; // 读写缓冲区内存池内存块个数 38 | unsigned int step; // 自动分配的内存块个数 39 | unsigned int size; // 每个读写数据区内存块的大小 40 | 41 | int listenNum; // 监听连接的队列长度 42 | unsigned int maxMsgSize; // 最大消息包长度,单个消息包大小超过此长度则关闭连接 43 | unsigned int checkConnectInterval; // 遍历所有连接时间间隔(检查连接活跃时间、心跳信息),单位毫秒 44 | unsigned int activeInterval; // 连接活跃检测间隔时间,单位秒,超过次间隔时间无数据则关闭连接 45 | unsigned short checkTimes; // 检查最大socket无数据的次数,超过此最大次数则连接移出消息队列,避免遍历一堆无数据的空连接 46 | unsigned short hbInterval; // 心跳检测间隔时间,单位秒 47 | unsigned char hbFailedTimes; // 心跳检测连续失败hbFailedTimes次后关闭连接 48 | }; 49 | 50 | 51 | class CConnectManager 52 | { 53 | public: 54 | CConnectManager(const char* ip, const int port, ILogicHandler* logicHandler); 55 | ~CConnectManager(); 56 | 57 | const char* getTcpIp(); 58 | 59 | 60 | public: 61 | int start(const ServerCfgData& cfgData); 62 | 63 | // 启动连接管理服务,waitTimeout:IO监听数据等待超时时间,单位毫秒; 64 | // isActive:是否主动收发网络数据 65 | int run(const int connectCount, const int waitTimeout, DataHandlerType dataHandlerType = ThreadHandle); 66 | void stop(); // 停止连接管理服务 67 | 68 | 69 | private: 70 | int doStart(const ServerCfgData& cfgData); 71 | void clear(); // 服务退出时清理所有资源 72 | void clearAllConnect(); // 关闭清理所有连接 73 | bool isRunning(); 74 | 75 | void reListen(Connect* listenConn); // 重新建立监听 76 | void acceptConnect(uint32_t eventVal, Connect* listenConn); // 建立新连接 77 | void handleConnect(uint32_t eventVal, Connect* conn); // 处理监听的连接(读写数据) 78 | void handleConnect(); // 处理所有连接(心跳检测,活跃检测,删除异常连接等等) 79 | 80 | private: 81 | Connect* createConnect(const int fd, const struct in_addr& peerIp, const unsigned short peerPort); 82 | void addInitedConnect(Connect* conn); 83 | 84 | void destroyConnect(Connect* conn); 85 | void destroyMsgConnect(Connect* conn); 86 | void destroyLoginConnect(Connect* conn); 87 | 88 | void removeConnect(Connect*& listHeader, Connect* conn); 89 | void closeConnect(Connect* conn); 90 | void setConnectNormal(Connect* conn); 91 | 92 | void addToMsgQueue(Connect* conn, const ConnectOpt opt); 93 | void removeFromMsgQueue(Connect* conn); 94 | 95 | private: 96 | bool readFromConnect(Connect* conn); 97 | bool writeToConnect(Connect* conn); 98 | 99 | CSingleW_SingleR_Buffer* getReadBuffer(); 100 | void releaseReadBuffer(CSingleW_SingleR_Buffer*& pBuffer); 101 | 102 | CSingleW_SingleR_Buffer* getBuffer(CMemManager* memMgr); 103 | void releaseBuffer(CMemManager* memMgr, CSingleW_SingleR_Buffer*& pBuff); 104 | 105 | private: 106 | void waitDataHandler(); // 等待数据处理线程处理完 107 | void notifyDataHandler(); // 通知数据处理线程执行处理操作 108 | 109 | private: 110 | // 处理本地端主动发起的连接 111 | void doActiveConnect(); 112 | int doActiveConnect(const char* peerIp, const unsigned short peerPort, int& fd, int& errorCode); 113 | void onActiveConnect(uint32_t eventVal, Connect* conn); 114 | bool checkActiveConnect(const struct in_addr& peerIp, const unsigned short peerPort, const int userId); // 检查是否对应的主动连接已经在建立中了 115 | void addErrorActiveConnect(unsigned int ip, unsigned short port); 116 | void removeErrorActiveConnect(unsigned int ip, unsigned short port); 117 | bool checkErrorActiveConnect(unsigned int ip, unsigned short port); 118 | 119 | 120 | // 提供给数据处理线程调用的API 121 | private: 122 | unsigned short getHbInterval() const; 123 | Connect* getMsgConnectList(); 124 | Connect* getMsgConnect(const uuid_type connId); 125 | 126 | CSingleW_SingleR_Buffer* getWriteBuffer(); 127 | void releaseWriteBuffer(CSingleW_SingleR_Buffer*& pBuffer); 128 | 129 | bool waitConnecter(); // 等待连接处理线程处理完 130 | 131 | 132 | private: 133 | CTcpConnect m_tcpListener; // 负责监听连接的socket 134 | CSocket m_activeConnect; // 本地端主动对其他外部节点建立连接 135 | CEpoll m_epoll; // epoll IO 监听复用 136 | 137 | IdToConnect m_connectMap; // id映射所有连接对象信息 138 | Connect* m_loginConnectList; // 主动建立的连接列表 139 | Connect* m_msgConnectList; // 建立的处理逻辑消息连接列表 140 | unsigned long long m_nextCheckTime; // 下次检测连接的时间点,单位毫秒 141 | 142 | CMemManager* m_memForRead; // 读socket缓冲区内存管理,连接管理线程使用 143 | CMemManager* m_memForWrite; // 写socket缓冲区内存管理,数据处理线程使用 144 | CMemManager* m_connMemory; // 连接内存管理 145 | 146 | uuid_type m_connId; // 各个连接的ID,从1开始 147 | ILogicHandler* m_logicHandler; // 业务逻辑处理,读写数据 148 | 149 | int m_listenNum; // 监听连接的队列长度 150 | 151 | SynNotify m_synNotify; // 连接线程&数据处理线程同步等待&通知 152 | unsigned int m_maxMsgSize; // 最大消息包长度,单个消息包大小超过此长度则关闭连接 153 | unsigned int m_checkConnectInterval; // 遍历所有连接时间间隔(检查连接活跃时间、心跳信息),单位毫秒 154 | unsigned int m_activeInterval; // 连接活跃检测间隔时间,单位秒,超过此间隔时间无数据则关闭连接 155 | unsigned short m_checkTimes; // 检查最大socket无数据的次数,超过此最大次数则连接移出消息队列,避免遍历一堆无数据的空连接 156 | unsigned short m_hbInterval; // 心跳检测间隔时间,单位秒 157 | unsigned char m_hbFailedTimes; // 心跳检测连续失败hbFailedTimes次后关闭连接 158 | char m_status; // 连接服务状态,0:停止;1:运行 159 | NodeIdToTimeSecs m_errorConns; // 主动连接,错误连接的下次发起时间 160 | 161 | 162 | // 禁止构造&拷贝&赋值类函数 163 | DISABLE_CONSTRUCTION_ASSIGN(CConnectManager); 164 | 165 | friend class CDataHandler; 166 | friend class CDataTransmit; 167 | friend class SynWaitNotify; 168 | }; 169 | 170 | } 171 | 172 | #endif // CCONNECT_MANAGER_H 173 | -------------------------------------------------------------------------------- /common/connect_lib/CDataHandler.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.12.17 4 | * description : 网络连接管理socket读写数据线程 5 | */ 6 | 7 | #ifndef CDATAHANDLER_H 8 | #define CDATAHANDLER_H 9 | 10 | #include "base/MacroDefine.h" 11 | #include "base/CThread.h" 12 | #include "ILogicHandler.h" 13 | #include "NetType.h" 14 | 15 | 16 | namespace NConnect 17 | { 18 | 19 | class CConnectManager; 20 | 21 | // 连接收发数据分析、数据处理对象 22 | class CDataHandler : public CThread, public IConnectMgr 23 | { 24 | public: 25 | CDataHandler(CConnectManager* connMgr, ILogicHandler* logicHandler); 26 | ~CDataHandler(); 27 | 28 | // 启动线程,逻辑层被动收发消息 29 | public: 30 | int startHandle(); 31 | void finishHandle(); 32 | bool isRunning(); 33 | 34 | virtual const char* getName(); // 线程名称 35 | 36 | // 由逻辑层主动收发消息 37 | public: 38 | virtual ReturnValue recv(Connect*& conn, char* data, unsigned int& len); 39 | virtual ReturnValue send(Connect* conn, const char* data, const unsigned int len, bool isNeedWriteMsgHeader = true); 40 | virtual void close(Connect* conn); 41 | 42 | public: 43 | static unsigned int getCanReadDataSize(Connect* conn); 44 | static unsigned int getCanWriteDataSize(Connect* conn); 45 | 46 | // 读写数据 47 | // isRead : 为false时从连接读出的数据会被直接丢弃,不会拷贝到data调用者空间 48 | static unsigned int read(Connect* conn, char* data, unsigned int len, bool isRead = true); 49 | 50 | static bool write(CConnectManager* connMgr, Connect* conn, const char* data, int len); 51 | static bool writeToSkt(CConnectManager* connMgr, Connect* conn, const char* data, const unsigned int len, int& wtLen); 52 | static void writeHbRequestPkg(CConnectManager* connMgr, Connect* curConn, unsigned int curSecs); 53 | static void releaseWrtBuff(CConnectManager* connMgr, Connect* conn); // 释放申请的连接写缓冲区 54 | 55 | private: 56 | // 读写数据 57 | // isRead : 为false时从连接读出的数据会被直接丢弃,不会拷贝到data调用者空间 58 | unsigned int readData(Connect* conn, char* data, unsigned int len, bool isRead = true); 59 | 60 | bool readPkgHeader(Connect* curConn, unsigned int& dataSize); 61 | bool readPkgBody(Connect* curConn, unsigned int dataSize, unsigned int& pkgLen, char* pkgData = NULL); 62 | 63 | bool writeData(Connect* conn, const char* data, int len); 64 | 65 | // 处理数据 66 | int handleData(Connect* msgConnList, NetPkgHeader& userPkgHeader); 67 | bool handleData(Connect* curConn, unsigned int dataSize, unsigned int curSecs, unsigned int& pkgLen, char* pkgData = NULL); 68 | bool readFromLogic(NetPkgHeader& userPkgHeader); 69 | 70 | // 释放申请的连接写缓冲区 71 | void releaseWriteBuffer(Connect* conn); 72 | 73 | private: 74 | virtual void run(); 75 | 76 | private: 77 | CConnectManager* m_connMgr; 78 | Connect* m_curConn; 79 | ILogicHandler* m_logicHandler; // 业务逻辑处理,读写数据 80 | char m_status; // 线程处理数据状态,停止;运行;正在停止中 81 | 82 | // 禁止构造&拷贝&赋值类函数 83 | DISABLE_CONSTRUCTION_ASSIGN(CDataHandler); 84 | }; 85 | 86 | 87 | 88 | 89 | // 提供给上层逻辑调用者调用 90 | class CLogicConnectMgr : public IConnectMgr 91 | { 92 | public: 93 | CLogicConnectMgr(CDataHandler* dataHandler); 94 | ~CLogicConnectMgr(); 95 | 96 | public: 97 | // 逻辑层直接从连接收发消息数据 98 | virtual ReturnValue recv(Connect*& conn, char* data, unsigned int& len); 99 | virtual ReturnValue send(Connect* conn, const char* data, const unsigned int len, bool isNeedWriteMsgHeader = true); 100 | 101 | public: 102 | virtual void close(Connect* conn); 103 | 104 | private: 105 | CDataHandler* m_dataHandler; 106 | 107 | // 禁止构造&拷贝&赋值类函数 108 | DISABLE_CONSTRUCTION_ASSIGN(CLogicConnectMgr); 109 | }; 110 | 111 | 112 | 113 | 114 | // 防止操作异常情况下线程不解锁 115 | class SynWaitNotify 116 | { 117 | public: 118 | SynWaitNotify(CConnectManager* connMgr); 119 | ~SynWaitNotify(); 120 | 121 | private: 122 | CConnectManager* m_connMgr; 123 | 124 | // 禁止构造&拷贝&赋值类函数 125 | DISABLE_CONSTRUCTION_ASSIGN(SynWaitNotify); 126 | }; 127 | 128 | 129 | } 130 | 131 | #endif // CDATAHANDLER_H 132 | -------------------------------------------------------------------------------- /common/connect_lib/CDataTransmit.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.06.30 4 | * description : 纯网络数据读写,不做数据解析、心跳监测等其他额外操作 5 | */ 6 | 7 | #include "CDataTransmit.h" 8 | #include "CDataHandler.h" 9 | #include "CConnectManager.h" 10 | #include "base/ErrorCode.h" 11 | 12 | 13 | using namespace NCommon; 14 | using namespace NErrorCode; 15 | 16 | namespace NConnect 17 | { 18 | 19 | CDataTransmit::CDataTransmit(CConnectManager* connMgr, ILogicHandler* logicHandler) : m_connMgr(connMgr), m_logicHandler(logicHandler) 20 | { 21 | m_curConn = NULL; 22 | } 23 | 24 | CDataTransmit::~CDataTransmit() 25 | { 26 | m_curConn = NULL; 27 | m_connMgr = NULL; 28 | m_logicHandler = NULL; 29 | } 30 | 31 | // 由逻辑层主动收发消息 32 | ReturnValue CDataTransmit::recv(Connect*& conn, char* data, unsigned int& len) 33 | { 34 | // 1)先过滤掉无效的连接 35 | while (m_curConn != NULL && m_curConn->logicStatus == ConnectStatus::deleted) m_curConn = m_curConn->pNext; 36 | 37 | // 2)接着等待连接处理线程处理完 38 | m_connMgr->waitConnecter(); 39 | if (m_curConn == NULL || m_curConn->checkSocketTimes == 0) // wait之后存在m_curConn可能被连接线程移出队列了 40 | { 41 | // wait之后可能存在多个连接被连接线程移出队列的情况,因此这里必须重新获取连接列表 42 | m_curConn = m_connMgr->getMsgConnectList(); 43 | if (m_curConn == NULL) return NotNetData; 44 | } 45 | 46 | unsigned int dataSize = 0; 47 | Connect* const beginConn = m_curConn; 48 | while (true) 49 | { 50 | if (m_curConn->connStatus == ConnectStatus::normal && m_curConn->logicStatus == ConnectStatus::normal) 51 | { 52 | dataSize = CDataHandler::getCanReadDataSize(m_curConn); // 当前可以从连接读取的数据量 53 | if (dataSize > 0) 54 | { 55 | m_connMgr->addToMsgQueue(m_curConn, ConnectOpt::EAddToQueue); // 正常则加入消息队列 56 | m_connMgr->setConnectNormal(m_curConn); // 有数据则填写活跃时间点 57 | 58 | if (dataSize > len) dataSize = len; 59 | len = CDataHandler::read(m_curConn, data, dataSize); 60 | 61 | // 这里必须切换到下一个连接,不可以处理完当前连接的所有消息才处理下一个连接,这样会被正常的大量消息包攻击,导致其他连接玩家的消息得不到处理 62 | conn = m_curConn; 63 | m_curConn = m_curConn->pNext; // 切换到下一个连接,以便均衡遍历所有连接 64 | return OptSuccess; 65 | } 66 | } 67 | 68 | // 删除销毁已经关闭的连接 69 | else if (m_curConn->connStatus == ConnectStatus::closed && m_curConn->logicStatus != ConnectStatus::deleted) 70 | { 71 | CDataHandler::releaseWrtBuff(m_connMgr, m_curConn); 72 | m_curConn->logicStatus = ConnectStatus::deleted; // 标志此连接为无效连接,可删除了 73 | } 74 | 75 | m_curConn = (m_curConn->pNext != NULL) ? m_curConn->pNext : m_connMgr->getMsgConnectList(); 76 | if (m_curConn == beginConn) break; // 回到循环起点了,无可处理的消息 77 | } 78 | 79 | return NotNetData; 80 | } 81 | 82 | ReturnValue CDataTransmit::send(Connect* conn, const char* data, const unsigned int len, bool isNeedWriteMsgHeader) 83 | { 84 | if (conn->connStatus != ConnectStatus::normal || conn->logicStatus != ConnectStatus::normal) // 无效连接的数据 85 | { 86 | close(conn); 87 | return ConnectException; 88 | } 89 | 90 | return CDataHandler::write(m_connMgr, conn, data, len) ? OptSuccess : SndDataFailed; // 2) 再把逻辑层的数据写到连接里 91 | } 92 | 93 | void CDataTransmit::close(Connect* conn) 94 | { 95 | if (conn == m_curConn) m_curConn = m_curConn->pNext; 96 | 97 | if (CDataHandler::getCanWriteDataSize(conn) > 0) 98 | { 99 | conn->logicStatus = ConnectStatus::sendClose; // 连接里的数据发送完毕后关闭连接 100 | } 101 | else 102 | { 103 | CDataHandler::releaseWrtBuff(m_connMgr, conn); 104 | conn->logicStatus = ConnectStatus::deleted; // 标志此连接为无效连接,可删除了 105 | } 106 | } 107 | 108 | } 109 | 110 | -------------------------------------------------------------------------------- /common/connect_lib/CDataTransmit.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.06.30 4 | * description : 纯网络数据读写,不做数据解析、心跳监测等其他额外操作 5 | */ 6 | 7 | #ifndef CDATATRANSMIT_H 8 | #define CDATATRANSMIT_H 9 | 10 | #include "base/MacroDefine.h" 11 | #include "ILogicHandler.h" 12 | #include "NetType.h" 13 | 14 | 15 | namespace NConnect 16 | { 17 | 18 | class CConnectManager; 19 | 20 | // 纯网络数据读写,不做数据解析、心跳监测等其他额外操作 21 | class CDataTransmit : public IConnectMgr 22 | { 23 | public: 24 | CDataTransmit(CConnectManager* connMgr, ILogicHandler* logicHandler); 25 | ~CDataTransmit(); 26 | 27 | // 由逻辑层主动收发消息 28 | public: 29 | virtual ReturnValue recv(Connect*& conn, char* data, unsigned int& len); 30 | virtual ReturnValue send(Connect* conn, const char* data, const unsigned int len, bool isNeedWriteMsgHeader = true); 31 | virtual void close(Connect* conn); 32 | 33 | private: 34 | CConnectManager* m_connMgr; 35 | Connect* m_curConn; 36 | ILogicHandler* m_logicHandler; // 业务逻辑处理,读写数据 37 | 38 | // 禁止构造&拷贝&赋值类函数 39 | DISABLE_CONSTRUCTION_ASSIGN(CDataTransmit); 40 | }; 41 | 42 | } 43 | 44 | #endif // CDATATRANSMIT_H 45 | -------------------------------------------------------------------------------- /common/connect_lib/CEpoll.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.30 4 | * description : epoll模型API封装实现 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "CEpoll.h" 13 | #include "base/MacroDefine.h" 14 | #include "base/ErrorCode.h" 15 | 16 | 17 | using namespace NCommon; 18 | using namespace NErrorCode; 19 | 20 | 21 | namespace NConnect 22 | { 23 | 24 | CEpoll::CEpoll() : m_epfd(-1) 25 | { 26 | } 27 | 28 | CEpoll::~CEpoll() 29 | { 30 | destroy(); 31 | } 32 | 33 | int CEpoll::create(int listenCount) 34 | { 35 | // 创建 epoll,Since Linux 2.6.8, the listenCount argument is ignored, but must be greater than zero 36 | if (listenCount < 1) 37 | { 38 | return InvalidParam; 39 | } 40 | 41 | int epfd = ::epoll_create(listenCount); 42 | if (epfd == -1) 43 | { 44 | ReleaseErrorLog("create epoll error = %d, info = %s", errno, strerror(errno)); 45 | return CreateEPollFailed; 46 | } 47 | 48 | m_epfd = epfd; 49 | return Success; 50 | } 51 | 52 | void CEpoll::destroy() 53 | { 54 | if (m_epfd != -1) 55 | { 56 | if (::close(m_epfd) != 0) 57 | { 58 | ReleaseErrorLog("close epoll error = %d, info = %s", errno, strerror(errno)); 59 | } 60 | m_epfd = -1; 61 | } 62 | } 63 | 64 | int CEpoll::listen(struct epoll_event* waitEvents, const int maxEvents, const int waitTimeout) 65 | { 66 | // 等待epoll事件的发生,一次无法输出全部事件,下次会继续输出,因此事件不会丢失 67 | int num = epoll_wait(m_epfd, waitEvents, maxEvents, waitTimeout); 68 | if (num == -1) 69 | { 70 | ReleaseErrorLog("epoll wait listen error = %d, info = %s", errno, strerror(errno)); 71 | } 72 | return num; 73 | } 74 | 75 | int CEpoll::addListener(int fd, struct epoll_event& optEv) 76 | { 77 | if (::epoll_ctl(m_epfd, EPOLL_CTL_ADD, fd, &optEv) == -1) 78 | { 79 | ReleaseErrorLog("add listener to epoll error = %d, info = %s", errno, strerror(errno)); 80 | return AddEPollListenerFailed; 81 | } 82 | return Success; 83 | } 84 | 85 | int CEpoll::modifyListenEvent(int fd, struct epoll_event& optEv) 86 | { 87 | if (::epoll_ctl(m_epfd, EPOLL_CTL_MOD, fd, &optEv) == -1) 88 | { 89 | ReleaseErrorLog("modify listen event in epoll error = %d, info = %s", errno, strerror(errno)); 90 | return ModifyEPollListenerFailed; 91 | } 92 | return Success; 93 | } 94 | 95 | int CEpoll::removeListener(int fd) 96 | { 97 | struct epoll_event optEv; 98 | optEv.data.ptr = NULL; 99 | optEv.events = 0; 100 | if (::epoll_ctl(m_epfd, EPOLL_CTL_DEL, fd, &optEv) == -1) // 删除监听 101 | { 102 | ReleaseErrorLog("remove listener from epoll error = %d, info = %s", errno, strerror(errno)); 103 | return RemoveEPollListenerFailed; 104 | } 105 | return Success; 106 | } 107 | 108 | } 109 | 110 | -------------------------------------------------------------------------------- /common/connect_lib/CEpoll.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.30 4 | * description : epoll模型API封装实现 5 | */ 6 | 7 | #ifndef CEPOLL_H 8 | #define CEPOLL_H 9 | 10 | 11 | struct epoll_event; 12 | 13 | namespace NConnect 14 | { 15 | 16 | class CEpoll 17 | { 18 | public: 19 | CEpoll(); 20 | ~CEpoll(); 21 | 22 | public: 23 | int create(int listenCount); 24 | void destroy(); 25 | int listen(struct epoll_event* waitEvents, const int maxEvents, const int waitTimeout); 26 | int addListener(int fd, struct epoll_event& optEv); 27 | int modifyListenEvent(int fd, struct epoll_event& optEv); 28 | int removeListener(int fd); 29 | 30 | private: 31 | // 禁止拷贝、赋值 32 | CEpoll(const CEpoll&); 33 | CEpoll& operator =(const CEpoll&); 34 | 35 | private: 36 | int m_epfd; 37 | 38 | }; 39 | 40 | } 41 | 42 | #endif // CEPOLL_H 43 | -------------------------------------------------------------------------------- /common/connect_lib/CSocket.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.15 4 | * description : 网络连接封装实现 5 | */ 6 | 7 | #ifndef CSOCKET_H 8 | #define CSOCKET_H 9 | 10 | #include 11 | #include "base/Type.h" 12 | 13 | 14 | namespace NConnect 15 | { 16 | 17 | class CSocket 18 | { 19 | public: 20 | CSocket(); 21 | CSocket(const char* ip, const unsigned short port); 22 | virtual ~CSocket(); 23 | 24 | public: 25 | static const char* toIPStr(const struct in_addr& ip); 26 | static unsigned int toIPInt(const char* ip); 27 | static int toIPInAddr(const char* ipStr, struct in_addr& ipInAddr); 28 | static int getOpt(int sockfd, int level, int optname, void* optval, socklen_t* optlen); 29 | 30 | public: 31 | int init(const char* ip, const unsigned short port); 32 | void unInit(); 33 | 34 | public: 35 | int open(int type); // type:tcp或者udp;SOCK_STREAM&SOCK_DGRAM 36 | int open(int family, int type, int protocol); 37 | int close(); 38 | 39 | public: 40 | int bind(); 41 | int listen(int num); 42 | 43 | public: 44 | int connect(int& errorCode); 45 | 46 | public: 47 | int setLinger(int onOff, int val); // 慎用该选项 48 | int setRcvBuff(int val); // 接受缓冲区大小,在connect&listen操作之前设置 49 | int setSndBuff(int val); // 发生缓冲区大小,在connect&listen操作之前设置 50 | int setReuseAddr(int val); // 地址重用,bind之前调用 51 | int setNagle(int val); // Nagle算法 52 | int setNoBlock(); // 设置为非主塞方式 53 | int setNoBlock(int fd); // 设置为非主塞方式 54 | 55 | public: 56 | int getFd() const; 57 | const char* getIp() const; 58 | unsigned short getPort() const; 59 | 60 | 61 | private: 62 | // 禁止拷贝、赋值 63 | CSocket(const CSocket&); 64 | CSocket& operator =(const CSocket&); 65 | 66 | protected: 67 | strIP_t m_ip; 68 | unsigned short m_port; 69 | int m_fd; 70 | }; 71 | 72 | } 73 | 74 | #endif // CSOCKET_H 75 | -------------------------------------------------------------------------------- /common/connect_lib/CTcpConnect.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.20 4 | * description : TCP连接相关实现 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "CTcpConnect.h" 16 | #include "base/MacroDefine.h" 17 | #include "base/ErrorCode.h" 18 | 19 | 20 | using namespace NCommon; 21 | using namespace NErrorCode; 22 | 23 | 24 | namespace NConnect 25 | { 26 | 27 | CTcpConnect::CTcpConnect(const char* ip, const int port) : CSocket(ip, port) 28 | { 29 | m_isNormal = false; 30 | } 31 | 32 | CTcpConnect::~CTcpConnect() 33 | { 34 | destroy(); 35 | } 36 | 37 | int CTcpConnect::create(int listenNum) 38 | { 39 | int rc = open(SOCK_STREAM); // tcp连接socket 40 | if (rc != Success) 41 | { 42 | return rc; 43 | } 44 | 45 | rc = setReuseAddr(1); 46 | if (rc != Success) 47 | { 48 | return rc; 49 | } 50 | 51 | // 屏蔽nagle算法,否则会有延迟错误 52 | // 类似场景:消息源端发送请求,等待目标端应答,但由于nagle算法目标端延迟应答,此时消息源端可能会触发超时操作流程而导致错误 53 | rc = setNagle(1); 54 | if (rc != Success) 55 | { 56 | return rc; 57 | } 58 | 59 | rc = setNoBlock(); 60 | if (rc != Success) 61 | { 62 | return rc; 63 | } 64 | 65 | rc = bind(); 66 | if (rc != Success) 67 | { 68 | return rc; 69 | } 70 | 71 | rc = listen(listenNum); 72 | m_isNormal = (rc == Success); 73 | 74 | return rc; 75 | } 76 | 77 | void CTcpConnect::destroy() 78 | { 79 | m_isNormal = false; 80 | close(); 81 | } 82 | 83 | bool CTcpConnect::isNormal() 84 | { 85 | return (m_fd > 0) && m_isNormal; 86 | } 87 | 88 | int CTcpConnect::accept(int& fd, in_addr& peerIp, unsigned short& peerPort, int& errorCode) 89 | { 90 | errorCode = Success; 91 | struct sockaddr_in peerAddr; 92 | socklen_t peerSize = sizeof(peerAddr); 93 | memset(&peerAddr, 0, peerSize); 94 | fd = ::accept(m_fd, (struct sockaddr*)&peerAddr, &peerSize); 95 | if (fd == -1) 96 | { 97 | errorCode = errno; 98 | if (errorCode != EAGAIN && errorCode != EINTR) 99 | { 100 | ReleaseErrorLog("accept connect server ip = %s, port = %d, error = %d, info = %s", m_ip, m_port, errno, strerror(errno)); 101 | } 102 | return AcceptConnectFailed; 103 | } 104 | 105 | memcpy(&peerIp, &peerAddr.sin_addr, sizeof(peerIp)); 106 | peerPort = ntohs(peerAddr.sin_port); 107 | 108 | return Success; 109 | } 110 | 111 | } 112 | 113 | -------------------------------------------------------------------------------- /common/connect_lib/CTcpConnect.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.20 4 | * description : TCP连接相关实现 5 | */ 6 | 7 | #ifndef CTCPCONNECT_H 8 | #define CTCPCONNECT_H 9 | 10 | #include "CSocket.h" 11 | 12 | 13 | struct in_addr; 14 | 15 | namespace NConnect 16 | { 17 | 18 | class CTcpConnect : public CSocket 19 | { 20 | public: 21 | CTcpConnect(const char* ip, const int port); 22 | ~CTcpConnect(); 23 | 24 | public: 25 | int create(int listenNum); 26 | void destroy(); 27 | bool isNormal(); 28 | 29 | public: 30 | int accept(int& fd, in_addr& peerIp, unsigned short& peerPort, int& errorCode); 31 | 32 | private: 33 | bool m_isNormal; 34 | }; 35 | 36 | } 37 | 38 | #endif // CTCPCONNECT_H 39 | -------------------------------------------------------------------------------- /common/connect_lib/CUdp.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.23 4 | * description : UDP相关实现 5 | */ 6 | 7 | #include "CUdp.h" 8 | #include "base/MacroDefine.h" 9 | #include "base/ErrorCode.h" 10 | 11 | 12 | using namespace NCommon; 13 | using namespace NErrorCode; 14 | 15 | namespace NConnect 16 | { 17 | 18 | CUdp::CUdp(const char* ip, const int port) : CSocket(ip, port) 19 | { 20 | } 21 | 22 | CUdp::~CUdp() 23 | { 24 | } 25 | 26 | int CUdp::create(int listenNum) 27 | { 28 | int rc = open(SOCK_DGRAM); // udp连接socket 29 | if (rc != Success) 30 | { 31 | return rc; 32 | } 33 | 34 | rc = setNoBlock(); 35 | if (rc != Success) 36 | { 37 | return rc; 38 | } 39 | 40 | rc = bind(); 41 | 42 | return rc; 43 | } 44 | 45 | void CUdp::destroy() 46 | { 47 | close(); 48 | } 49 | 50 | size_t CUdp::recvFrom(void *buf, size_t len, struct sockaddr *src_addr, socklen_t *addrlen) 51 | { 52 | return ::recvfrom(m_fd, buf, len, 0, src_addr, addrlen); 53 | } 54 | 55 | size_t CUdp::sendTo(const void *buf, size_t len, const struct sockaddr *dest_addr, socklen_t addrlen) 56 | { 57 | return ::sendto(m_fd, buf, len, 0, dest_addr, addrlen); 58 | } 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /common/connect_lib/CUdp.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.23 4 | * description : UDP相关实现 5 | */ 6 | 7 | #ifndef CUDP_H 8 | #define CUDP_H 9 | 10 | #include "CSocket.h" 11 | 12 | namespace NConnect 13 | { 14 | 15 | class CUdp : public CSocket 16 | { 17 | public: 18 | CUdp(const char* ip, const int port); 19 | ~CUdp(); 20 | 21 | public: 22 | int create(int listenNum); 23 | void destroy(); 24 | size_t recvFrom(void *buf, size_t len, struct sockaddr *src_addr, socklen_t *addrlen); 25 | size_t sendTo(const void *buf, size_t len, const struct sockaddr *dest_addr, socklen_t addrlen); 26 | 27 | }; 28 | 29 | } 30 | 31 | #endif // CUDP_H 32 | -------------------------------------------------------------------------------- /common/connect_lib/ILogicHandler.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.12.16 4 | * description : 连接管理使用者,上层业务逻辑需实现的接口 5 | */ 6 | 7 | #ifndef ILOGIC_HANDLER_H 8 | #define ILOGIC_HANDLER_H 9 | 10 | #include "NetType.h" 11 | 12 | 13 | namespace NConnect 14 | { 15 | 16 | // 接口返回码 17 | enum ReturnValue 18 | { 19 | OptSuccess = 0, // 操作成功 20 | OptFailed = 1, // 操作&读写失败 21 | 22 | CloseConnect = 2, // logic 层要求关闭该连接 23 | InComplete = 3, // logic 层未处理完事务,继续等待处理 24 | 25 | ConnectException = 4, // 连接异常,该连接将被连接管理模块主动关闭 26 | SndDataFailed = 5, // 逻辑层往连接里发送数据失败 27 | NonExistConnect = 6, // 逻辑层往不存在的连接里收发数据 28 | 29 | ActiveConnecting = 7, // 主动发起的连接正在创建中 30 | ActiveConnTimeOut = 8, // 主动发起创建连接超时 31 | ActiveConnIpPortErr = 9, // IP或者Port无效,Port必须大于2000,防止和系统端口号冲突 32 | ActiveConnError = 10, // 主动发起创建连接错误 33 | 34 | NotNetData = 11, // 无网络数据可收 35 | SendDataCloseConnect = 12, // logic 层要求连接里的数据发送完毕后直接关闭连接 36 | 37 | PeerIpInBlackList = 13, // 连接对端的IP,在黑名单中 38 | PeerIpWhiteListMode = 14, // 连接对端的IP,开启白名单模式 39 | PeerIpInvalid = 15, // 连接对端的IP,无效的IP值 40 | }; 41 | 42 | 43 | // 网络连接码流的头部数据 44 | struct BufferHeader 45 | { 46 | char* header; 47 | unsigned int len; // header 的实际长度大小 48 | }; 49 | 50 | 51 | // 主动连接数据 52 | // 本地端主动创建连接 peerIp&peerPort 为连接对端的IP、端口号 53 | // peerPort : 必须大于2000,防止和系统端口号冲突 54 | // timeOut : 最长timeOut秒后连接还没有建立成功则关闭,并回调返回创建连接超时;单位秒 55 | // userCb : 主动发起建立连接时用户挂接的数据,连接建立过程中会通过回调传回应用层 56 | // userId : 主动发起建立连接时用户传递的ID,连接建立过程中会通过回调传回应用层 57 | // peerIp&peerPort&userId 唯一标识一个主动连接,三者都相同则表示是同一个连接 58 | struct ActiveConnect 59 | { 60 | ActiveConnect* next; 61 | unsigned int timeOut; 62 | void* userCb; 63 | int userId; 64 | strIP_t peerIp; 65 | unsigned short peerPort; 66 | }; 67 | 68 | 69 | // 提供给上层逻辑调用者主动调用 70 | class IConnectMgr 71 | { 72 | public: 73 | virtual ~IConnectMgr() {}; 74 | 75 | public: 76 | // 逻辑层直接从连接收发消息数据 77 | virtual ReturnValue recv(Connect*& conn, char* data, unsigned int& len) = 0; 78 | virtual ReturnValue send(Connect* conn, const char* data, const unsigned int len, bool isNeedWriteMsgHeader = true) = 0; 79 | 80 | public: 81 | virtual void close(Connect* conn) = 0; 82 | }; 83 | 84 | 85 | // 逻辑层实现该接口 86 | // 使用连接管理的逻辑层实现的接口,连接管理模块调用 87 | class ILogicHandler 88 | { 89 | public: 90 | virtual ~ILogicHandler() {}; 91 | 92 | // 以下API为连接管理模块主动调用 93 | public: 94 | // 本地端主动创建连接 peerIp&peerPort 为连接对端的IP、端口号 95 | // peerPort : 必须大于2000,防止和系统端口号冲突 96 | // timeOut : 最长timeOut秒后连接还没有建立成功则关闭,并回调返回创建连接超时;单位秒 97 | virtual ActiveConnect* getConnectData() = 0; 98 | 99 | // 主动连接建立的时候调用 100 | // conn 为连接对应的数据,peerIp&peerPort 为连接对端的IP地址和端口号 101 | // rtVal : 返回连接是否创建成功 102 | // 网络管理层根据逻辑层返回码判断是否需要关闭该连接,返回码为 [CloseConnect, SendDataCloseConnect] 则关闭该连接 103 | virtual ReturnValue doCreateConnect(Connect* conn, const char* peerIp, const unsigned short peerPort, ReturnValue rtVal, void*& userCb) = 0; 104 | 105 | public: 106 | // 被动连接建立的时候调用 107 | // conn 为连接对应的数据,peerIp & peerPort 为连接对端的IP地址和端口号 108 | // 网络管理层根据逻辑层返回码判断是否需要关闭该连接,返回码为 [CloseConnect, SendDataCloseConnect] 则关闭该连接 109 | virtual ReturnValue onCreateConnect(Connect* conn, const char* peerIp, const unsigned short peerPort, void*& userCb) = 0; 110 | 111 | public: 112 | // 成功建立了的连接才会回调该关闭接口 113 | virtual void onClosedConnect(Connect* conn, void* userCb) = 0; // 通知逻辑层连接已被关闭 114 | virtual void onInvalidConnect(const uuid_type connId, void* userCb) = 0; // 通知逻辑层connId对应的连接无效了,可能找不到,或者异常被关闭了,不能读写数据等等 115 | 116 | 117 | public: 118 | // 从逻辑层获取数据缓冲区,把从连接读到的数据写到该缓冲区 119 | // 返回NULL值则不会读取数据;返回非NULL值则先从连接缓冲区读取len的数据长度,做为getWriteBuffer接口的bufferHeader输入参数 120 | // 该接口一般做为先读取消息头部,用于解析消息头部使用 121 | virtual BufferHeader* getBufferHeader() = 0; 122 | 123 | // 返回值为 (char*)-1 则表示直接丢弃该数据;返回值为非NULL则读取数据;返回值为NULL则不读取数据 124 | virtual char* getWriteBuffer(const int len, const uuid_type connId, BufferHeader* bufferHeader, void*& cb) = 0; 125 | virtual void submitWriteBuffer(char* buff, const int len, const uuid_type connId, void* cb) = 0; 126 | 127 | public: 128 | // 从逻辑层获取数据缓冲区,把该数据写入connLogicId对应的连接里 129 | // isNeedWriteMsgHeader 是否需要写入网络数据消息头部信息,默认会写消息头信息 130 | // isNeedWriteMsgHeader 如果逻辑层调用者填值为false,则调用者必须自己写入网络消息头部数据,即返回的可读buff中已经包含了网络消息头数据 131 | virtual char* getReadBuffer(int& len, uuid_type& connId, bool& isNeedWriteMsgHeader, void*& cb) = 0; 132 | virtual void submitReadBuffer(char* buff, const int len, const uuid_type connId, void* cb) = 0; 133 | 134 | 135 | public: 136 | // 直接从从逻辑层读写消息数据,多了一次中间数据拷贝,性能较低 137 | virtual ReturnValue readData(char* data, int& len, uuid_type& connId) = 0; 138 | virtual ReturnValue writeData(const char* data, const int len, const uuid_type connId) = 0; 139 | 140 | 141 | public: 142 | // 设置连接收发数据接口对象 143 | virtual void setConnMgrInstance(IConnectMgr* instance) = 0; 144 | 145 | public: 146 | // 检查连接对端的IP是否合法,IP地址白名单&黑名单使用 147 | virtual ReturnValue checkPeerIp(unsigned int peerIp) {return ReturnValue::OptSuccess;} 148 | }; 149 | 150 | } 151 | 152 | 153 | #endif // ILOGIC_HANDLER_H 154 | 155 | -------------------------------------------------------------------------------- /common/connect_lib/Makefile: -------------------------------------------------------------------------------- 1 | INC_PATH := -I/usr/local/include -I../../common 2 | CFLAGS = -static $(INC_PATH) -g -Wall -o2 -std=c++0x 3 | CC=g++ 4 | SRC=$(wildcard *.cpp) 5 | OBJ=$(addprefix ./, $(addsuffix .o, $(basename $(SRC)))) 6 | TARGET=../../../lib/libconnect.a 7 | 8 | all: $(TARGET) 9 | 10 | $(TARGET): $(OBJ) 11 | $(AR) -rcs $@ $^ 12 | rm -f $(OBJ) 13 | 14 | %.o: %.c 15 | $(CC) $(CFLAGS) -o $@ -c $< 16 | 17 | %.o: %.cpp 18 | $(CC) $(CFLAGS) -o $@ -c $< 19 | 20 | clean: 21 | rm -f $(TARGET) $(OBJ) 22 | -------------------------------------------------------------------------------- /common/connect_lib/NetType.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2014.11.19 4 | * description : 网络管理模块各种类型定义 5 | */ 6 | 7 | #ifndef NET_TYPE_H 8 | #define NET_TYPE_H 9 | 10 | #include 11 | 12 | #include "base/Type.h" 13 | #include "base/CSingleW_SingleR_Buffer.h" 14 | #include "base/CMutex.h" 15 | #include "base/CCond.h" 16 | 17 | 18 | using namespace NCommon; 19 | 20 | namespace NConnect 21 | { 22 | 23 | enum DataHandlerType 24 | { 25 | ThreadHandle = 0, // 由网络层内部创建线程主动收发、解析处理数据 26 | NetDataParseActive = 1, // 网络层内部解析处理数据,外部主动调用收发数据消息包 27 | DataTransmit = 2, // 网络层内部不解析数据,外部主动调用收发、解析纯网络数据 28 | }; 29 | 30 | // 连接&逻辑处理状态 31 | enum ConnectStatus 32 | { 33 | normal = 0, // 连接正常,可读写数据 [连接线程] 填写 34 | closed = 1, // 连接已关闭,通知读写线程连接关闭,等待读写数据线程取走缓冲区中的数据 [连接线程] 填写 35 | connecting = 2, // 本地端发起的主动连接处于正在建立的过程中,还没有完全建立成功完毕 [连接线程] 填写 36 | deleted = 3, // 读写线程已取走缓冲区数据,直到此时连接管理线程才可以真正删除连接 [数据处理线程] 填写 37 | exception = 4, // 连接对应的逻辑处理发生异常,需要直接断开并删除此连接 [数据处理线程] 填写 38 | sendClose = 5, // 连接里的数据发送完毕后直接关闭连接 [数据处理线程] 填写 39 | }; 40 | 41 | // 连接关联的数据,注意字节对齐 42 | struct Connect 43 | { 44 | Connect* pPre; // 连接链表中的前一个连接 45 | Connect* pNext; // 连接链表中的下一个连接 46 | 47 | CSingleW_SingleR_Buffer* readBuff; // 从socket连接里读数据放入此缓冲区,由 [连接线程] 创建&修改&释放 48 | CSingleW_SingleR_Buffer* curReadIdx; // 当前读buff索引,由 [数据处理线程] 使用不断修改 49 | 50 | CSingleW_SingleR_Buffer* writeBuff; // 把此缓冲区的数据写入socekt连接,由 [数据处理线程] 创建&修改&释放 51 | CSingleW_SingleR_Buffer* curWriteIdx; // 当前写buff索引,由 [连接线程] 使用不断修改 52 | 53 | unsigned int heartBeatSecs; // 上次心跳时间,即上次发送心跳的时间点,单位秒,由 [数据处理线程] 发送心跳消息时填写 54 | unsigned int activeSecs; // 上次活跃时间,即上次收到用户数据的时间点,单位秒,由 [数据处理线程] 读出socket数据时填写 55 | int needReadSize; // 需要从readBuff中读取的数据长度,为0时表示读取数据包头部大小,大于0时表示读取数据包体,由 [数据处理线程] 读出socket数据时填写 56 | 57 | void* userCb; // 用户挂接的回调数据 58 | int userId; // 用户挂接的ID 59 | uuid_type id; // 连接ID 60 | int fd; // 连接socket描述符 61 | unsigned short checkSocketTimes; // 按一定时间间隔检查socket,没有数据的次数 62 | unsigned short peerPort; // 连接对端的端口号 63 | struct in_addr peerIp; // 连接对端的ip 64 | 65 | unsigned char hbResult; // 心跳检查结果:0正常,大于0则为心跳检测的连续失败次数,由 [数据处理线程] 填写 66 | unsigned char logicStatus; // 该连接对应的逻辑处理状态:0正常,2可删除,3逻辑异常,5发送数据完毕后关闭连接;由 [数据处理线程] 填写 67 | unsigned char connStatus; // 连接的状态:0正常,1关闭,2连接处在建立过程;由 [连接线程] 填写 68 | unsigned char canWrite; // 连接是否可写:0不可写,1连接可写;由 [连接线程] 填写 69 | }; 70 | 71 | 72 | // 线程处理者状态 73 | enum HandlerStatus 74 | { 75 | parallel = 0, // 连接线程&数据处理线程,并发执行 76 | waitDH = 1, // 连接线程等待数据处理线程 77 | waitConn = 2, // 数据处理线程等待连接线程 78 | }; 79 | 80 | // 连接管理线程和数据处理线程同步条件,注意字节对齐 81 | struct SynNotify 82 | { 83 | CMutex waitDataHandlerMutex; // 连接线程等待数据读写线程 84 | CCond waitDataHandlerCond; // 条件变量通知 85 | 86 | CMutex waitConnecterMutex; // 数据读写线程等待连接线程 87 | CCond waitConnecterCond; // 条件变量通知 88 | 89 | volatile int status; // parallel 0:并发执行; waitDH 1:连接线程等待数据处理线程; waitConn 2:数据处理线程等待连接线程 90 | }; 91 | 92 | 93 | // 网络数据包类型 94 | enum NetPkgType 95 | { 96 | MSG = 0, // 用户消息包 97 | CTL = 1, // 控制类型包 98 | }; 99 | 100 | // 控制标示符 101 | enum CtlFlag 102 | { 103 | HB_RQ = 0, // 心跳请求包,发往对端 104 | HB_RP = 1, // 心跳应答包,来自对端 105 | 106 | BLACK_LIMIT = 2, // 黑名单限制包,发往对端后服务器关闭连接 107 | WHITE_LIMIT = 3, // 白名单限制包,发往对端后服务器关闭连接 108 | }; 109 | 110 | // 网络数据包头部,注意字节对齐 111 | // 1)len字段必填写,并且需要转成网络字节序 112 | // 2)如果是用户协议消息,其他字段为0;如果是控制消息则根据类型填写 113 | #pragma pack(1) 114 | struct NetPkgHeader 115 | { 116 | uint32_t len; // 数据包总长度,包括包头+包体 117 | uchar8_t type; // 数据包类型 NetPkgType ,用户消息包则值为 0 118 | uchar8_t cmd; // 控制信息 CtlFlag 119 | uchar8_t ver; // 版本号,目前为 0 120 | uchar8_t res; // 保留字段,目前为 0 121 | 122 | NetPkgHeader() {} 123 | NetPkgHeader(uint32_t _len, uchar8_t _type, uchar8_t _cmd) : len(_len), type(_type), cmd(_cmd), ver(0), res(0) {} 124 | ~NetPkgHeader() {} 125 | }; 126 | #pragma pack() 127 | 128 | } 129 | 130 | 131 | #endif // NET_TYPE_H 132 | -------------------------------------------------------------------------------- /common/connect_lib/readme: -------------------------------------------------------------------------------- 1 | net lib code, 2 | 网络库(socket、TCP、UDP、epoll机制、连接自动收发消息等等)实现代码。 3 | -------------------------------------------------------------------------------- /common/db_lib/CRedis.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.30 4 | * description : redis client api 5 | */ 6 | 7 | #ifndef __CREDIS_H__ 8 | #define __CREDIS_H__ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "base/ErrorCode.h" 14 | 15 | /* redis 接口注意事项 16 | * 1、使用get接口时,当返回结果为0(长度)时,该key有可能不存在,也有可能key对应的值为空,若想确定是否为空,需调用对应的 has接口, 17 | 除非你的业务能保证不存在非空值的value. 18 | * 2、使用has接口时,当返回结果 大于等于1 时,才说明该Key存在,因为当出现网络错误时会返回负数,切记不要这样if(has()),得这样使用if(has() > 0) 19 | */ 20 | namespace NDBOpt 21 | { 22 | 23 | class CRedis 24 | { 25 | public: 26 | CRedis(); 27 | ~CRedis(); 28 | 29 | //服务器连接 30 | bool connectSvr(const char *ip, int port, unsigned int timeout = 1500); //timeout 单位ms 31 | void disconnectSvr(); 32 | 33 | //同步数据到磁盘 34 | int asynSave();//异步,会立即返回 35 | int save();//同步,耗时长,慎用 36 | 37 | //redis 原始接口 38 | void* command(const char *format, ...); 39 | void* commandArgv(const std::vector &vstrOper, const std::vector &vstrParam); 40 | 41 | //redis基本操作(string)(数值类型得格式化成string) 42 | int setKey(const char *key, int keyLen, const char *value, int valueLen, unsigned int lifeTime = 0);//lifeTime,生存时间(秒),0代表永不删除 43 | int setKeyRange(const char *key, int keyLen, int offset, const char *value, int valueLen);//offset为偏移量,下标从0开始 44 | int append(const char *key, int keyLen, const char *value, int valueLen);//在原有的key追加,若不存在则相当于setKey 45 | int setKeyLifeTime(const char *key, int keyLen, unsigned int time = 0); //time 单位秒,=0代表永不删除 46 | 47 | int getKey(const char *key, int keyLen, char *value, int valueLen);//结果存value,返回长度,0不存在 48 | int getLen(const char *key, int keyLen);//返回结果:0代表不存在 49 | int getKeyByRange(const char *key, int keyLen, int start, int end, char *value, int valueLen);//start,end, -1代表最后1个,-2代表倒数第2个 50 | int getKeyRemainLifeTime(const char *key, int keyLen);//返回结果:-2:key不存在,-1:永久,其它则返回剩余时间(秒) 51 | int getKeyType(const char *key, int keyLen, char *valueType, int valueLen);//返回结果在valueType 52 | 53 | int delKey(const char *key, int keyLen);//删除成功返回1,不存在返回0 54 | int hasKey(const char *key, int keyLen);//key存在返回1,不存在返回0 55 | int incrByFloat(const char *key, int keyLen, double addValue, double &retValue);//执行成功返回0 56 | 57 | int setMultiKey(const std::vector &vstrKeyValue);//返回0 成功 58 | int getMultiKey(const std::vector &vstrKey, std::vector &vstrValue);//返回0 成功,结果在vstrValue中 59 | int delMultiKey(const std::vector &vstrKey);//返回删除成功的个数 60 | 61 | //hash表 62 | int setHField(const char *key, int keyLen, const char *field, int fieldLen, const char *value, int valueLen);//返回0 成功 63 | int getHField(const char *key, int keyLen, const char *field, int fieldLen, char *value, int valueLen);//返回长度 64 | int delHField(const char *key, int keyLen, const char *field, int fieldLen);//删除成功返回1,不存在返回0 65 | 66 | int hasHField(const char *key, int keyLen, const char *field, int fieldLen);//key存在返回1,不存在返回0 67 | int incrHByFloat(const char *key, int keyLen, const char *field, int fieldLen, double addValue, double retValue);//执行成功返回0 68 | int getHAll(const char *key, int keyLen, std::vector &vstrFieldValue);//执行成功返回0 69 | int getHFieldCount(const char *key, int keyLen);//返回field个数 70 | 71 | int setMultiHField(const char *key, int keyLen, const std::vector &vstrFieldValue);//返回0 成功 72 | int getMultiHField(const char *key, int keyLen, const std::vector &vstrField, std::vector &vstrValue);//返回0 成功 73 | int delMultiHField(const char *key, int keyLen, const std::vector &vstrField);//返回删除成功的个数 74 | 75 | //列表 76 | int lpushList(const char *key, int keyLen, const char *value, int valueLen);//返回列表长度 77 | int lpopList(const char *key, int keyLen, char *value, int valueLen);//返回value长度 78 | int rpushList(const char *key, int keyLen, const char *value, int valueLen);//返回列表长度 79 | int rpopList(const char *key, int keyLen, char *value, int valueLen);//返回value长度 80 | 81 | int indexList(const char *key, int keyLen, int index, char *value, int valueLen);//返回value长度 82 | int lenList(const char *key, int keyLen);//成功长度 83 | int rangeList(const char *key, int keyLen, int start, int end, std::vector &vstrList);//成功返回0 84 | int setList(const char *key, int keyLen, int index, const char *value, int valueLen);//成功返回0,set效率为线性的,一般只用做首尾的修改(也就是index为0或-1) 85 | 86 | private: 87 | // 禁止拷贝、赋值 88 | CRedis(const CRedis&); 89 | CRedis& operator =(const CRedis&); 90 | bool reConnectSvr(); 91 | void *execCommand(const char *cmd, int len); 92 | 93 | private: 94 | redisContext *m_predisContext; 95 | 96 | std::string m_strIP; 97 | int m_nPort; 98 | unsigned int m_nTimeout; 99 | }; 100 | 101 | } 102 | 103 | #endif // CREDIS_H 104 | 105 | 106 | -------------------------------------------------------------------------------- /common/db_lib/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -static -I/usr/local/include -I../../../import/third_party/include -I../../../import/third_party/include/mysql -I../../common -g -Wall -o2 -std=c++0x 2 | CFLAGS += #调试日志开关,编译运行版本的时候注释掉该选项 3 | CC=g++ 4 | SRC=$(wildcard *.cpp) 5 | OBJ=$(addprefix ./, $(addsuffix .o, $(basename $(SRC)))) 6 | TARGET=../../../lib/libdb.a 7 | 8 | all: $(TARGET) 9 | 10 | $(TARGET): $(OBJ) 11 | $(AR) -rcs $@ $^ 12 | rm -f $(OBJ) 13 | 14 | %.o: %.c 15 | $(CC) $(CFLAGS) -o $@ -c $< 16 | 17 | %.o: %.cpp 18 | $(CC) $(CFLAGS) -o $@ -c $< 19 | 20 | clean: 21 | rm -f $(TARGET) $(OBJ) 22 | -------------------------------------------------------------------------------- /common/db_lib/readme: -------------------------------------------------------------------------------- 1 | db operate lib code,数据库操作库(mysql,redis、memcache API 封装可直接调用)。 2 | -------------------------------------------------------------------------------- /common/readme: -------------------------------------------------------------------------------- 1 | 基础库(配置文件读写、日志、多线程、多进程、锁、对象引用计数、内存池、免锁消息队列、免锁数据缓冲区、进程信号、共享内存、定时器等等基础功能组件), 2 | 网络库(socket、TCP、UDP、epoll机制、连接自动收发消息等等), 3 | 数据库操作库(mysql,redis、memcache API 封装可直接调用)实现。 4 | -------------------------------------------------------------------------------- /frame/SrvFrame/CConnectMgr.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.10.12 4 | * description : 连接对象管理 5 | */ 6 | 7 | #include "CConnectMgr.h" 8 | #include "CNetMsgComm.h" 9 | #include "CService.h" 10 | 11 | 12 | namespace NFrame 13 | { 14 | 15 | static const unsigned int MaxProxyDataCount = 512; // 为代理数据一次性分配的内存块个数 16 | 17 | extern CService& getService(); // 获取服务实例 18 | 19 | 20 | CConnectMgr::CConnectMgr() : m_memForProxyData(MaxProxyDataCount, MaxProxyDataCount, sizeof(ConnectProxy)) 21 | { 22 | m_netMsgComm = NULL; 23 | } 24 | 25 | CConnectMgr::~CConnectMgr() 26 | { 27 | m_netMsgComm = NULL; 28 | } 29 | 30 | void CConnectMgr::setNetMsgComm(CNetMsgComm* netMsgComm) 31 | { 32 | m_netMsgComm = netMsgComm; 33 | } 34 | 35 | // 提供 实际网络连接对象 的保存、关闭、增删查等(应用上层)操作 36 | void CConnectMgr::addConnect(const string& connId, Connect* conn, void* userData) 37 | { 38 | conn->userCb = userData; 39 | m_id2Connects[connId] = conn; 40 | } 41 | 42 | bool CConnectMgr::removeConnect(const string& connId, bool doClose) 43 | { 44 | IDToConnects::iterator it = m_id2Connects.find(connId); 45 | if (it != m_id2Connects.end()) 46 | { 47 | Connect* conn = it->second; 48 | m_id2Connects.erase(it); 49 | if (doClose) m_netMsgComm->close(conn); // 必须先删除再回调,存在回调函数里应用上层遍历m_id2Connects的场景 50 | return true; 51 | } 52 | 53 | return false; 54 | } 55 | 56 | bool CConnectMgr::haveConnect(const string& connId) 57 | { 58 | return (m_id2Connects.find(connId) != m_id2Connects.end()); 59 | } 60 | 61 | void CConnectMgr::closeConnect(const string& connId) 62 | { 63 | IDToConnects::iterator it = m_id2Connects.find(connId); 64 | if (it != m_id2Connects.end()) m_netMsgComm->close(it->second); 65 | } 66 | 67 | void CConnectMgr::closeConnect(Connect* conn) 68 | { 69 | if (conn != NULL) m_netMsgComm->close(conn); 70 | } 71 | 72 | Connect* CConnectMgr::getConnect(const string& connId) 73 | { 74 | IDToConnects::iterator it = m_id2Connects.find(connId); 75 | return (it != m_id2Connects.end()) ? it->second : NULL; 76 | } 77 | 78 | const IDToConnects& CConnectMgr::getConnect() 79 | { 80 | return m_id2Connects; 81 | } 82 | 83 | void* CConnectMgr::getUserData(Connect* conn) 84 | { 85 | return (conn != NULL) ? conn->userCb : NULL; 86 | } 87 | 88 | 89 | 90 | // 提供 连接代理对象 的保存、关闭、增删查等(应用上层)操作 91 | void CConnectMgr::addConnectProxy(const string& connId, ConnectProxy* conn, void* userData) 92 | { 93 | conn->userCb = userData; 94 | m_id2ConnectProxys[connId] = conn; 95 | } 96 | 97 | bool CConnectMgr::removeConnectProxy(const string& connId, bool doClose, int cbFlag) 98 | { 99 | IDToConnectProxys::iterator it = m_id2ConnectProxys.find(connId); 100 | if (it != m_id2ConnectProxys.end()) 101 | { 102 | ConnectProxy* conn = it->second; 103 | m_id2ConnectProxys.erase(it); // 先删除,否则如果回调函数closeProxy里也执行同样的删除操作会导致it失效错误 104 | if (doClose) getService().closeProxy(conn, true, cbFlag); 105 | return true; 106 | } 107 | 108 | return false; 109 | } 110 | 111 | bool CConnectMgr::haveConnectProxy(const string& connId) 112 | { 113 | return (m_id2ConnectProxys.find(connId) != m_id2ConnectProxys.end()); 114 | } 115 | 116 | bool CConnectMgr::closeConnectProxy(const string& connId, int cbFlag) 117 | { 118 | return removeConnectProxy(connId, true, cbFlag); 119 | } 120 | 121 | void CConnectMgr::closeConnectProxy(ConnectProxy* conn, int cbFlag) 122 | { 123 | if (conn != NULL) getService().closeProxy(conn, true, cbFlag); 124 | } 125 | 126 | void CConnectMgr::clearConnectProxy() 127 | { 128 | m_id2ConnectProxys.clear(); 129 | } 130 | 131 | ConnectProxy* CConnectMgr::getConnectProxy(const string& connId) 132 | { 133 | IDToConnectProxys::iterator it = m_id2ConnectProxys.find(connId); 134 | return (it != m_id2ConnectProxys.end()) ? it->second : NULL; 135 | } 136 | 137 | const IDToConnectProxys& CConnectMgr::getConnectProxy() 138 | { 139 | return m_id2ConnectProxys; 140 | } 141 | 142 | void* CConnectMgr::getProxyUserData(ConnectProxy* conn) 143 | { 144 | return (conn != NULL) ? conn->userCb : NULL; 145 | } 146 | 147 | 148 | 149 | // 代理操作(框架底层) 150 | void CConnectMgr::addProxy(uuid_type flag, ConnectProxy* conn) 151 | { 152 | m_flag2Proxys[flag] = conn; 153 | } 154 | 155 | ConnectProxy* CConnectMgr::removeProxy(uuid_type flag) 156 | { 157 | return removeProxy(m_flag2Proxys.find(flag)); 158 | } 159 | 160 | ConnectProxy* CConnectMgr::removeProxy(FlagToProxys::iterator it) 161 | { 162 | ConnectProxy* conn = NULL; 163 | if (it != m_flag2Proxys.end()) 164 | { 165 | conn = it->second; 166 | m_flag2Proxys.erase(it); 167 | } 168 | 169 | return conn; 170 | } 171 | 172 | void CConnectMgr::clearProxy() 173 | { 174 | m_flag2Proxys.clear(); 175 | } 176 | 177 | bool CConnectMgr::haveProxy(uuid_type flag, FlagToProxys::iterator& it) 178 | { 179 | it = m_flag2Proxys.find(flag); 180 | return (it != m_flag2Proxys.end()); 181 | } 182 | 183 | ConnectProxy* CConnectMgr::getProxy(uuid_type flag) 184 | { 185 | FlagToProxys::iterator it = m_flag2Proxys.find(flag); 186 | return (it != m_flag2Proxys.end()) ? it->second : NULL; 187 | } 188 | 189 | const FlagToProxys& CConnectMgr::getProxy() 190 | { 191 | return m_flag2Proxys; 192 | } 193 | 194 | ConnectProxy* CConnectMgr::createProxy() 195 | { 196 | return (ConnectProxy*)m_memForProxyData.get(); 197 | } 198 | 199 | void CConnectMgr::destroyProxy(ConnectProxy*& conn) 200 | { 201 | m_memForProxyData.put((char*)conn); 202 | conn = NULL; 203 | } 204 | 205 | } 206 | 207 | -------------------------------------------------------------------------------- /frame/SrvFrame/CConnectMgr.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.10.12 4 | * description : 连接对象管理 5 | */ 6 | 7 | #ifndef CCONNECT_MGR_H 8 | #define CCONNECT_MGR_H 9 | 10 | #include 11 | #include 12 | 13 | #include "FrameType.h" 14 | #include "base/MacroDefine.h" 15 | #include "base/CMemManager.h" 16 | 17 | 18 | using namespace std; 19 | using namespace NCommon; 20 | using namespace NConnect; 21 | 22 | namespace NFrame 23 | { 24 | 25 | // 代理ID 26 | union ProxyID 27 | { 28 | uuid_type id; 29 | struct ProxyFlagData 30 | { 31 | int flag; 32 | unsigned int serviceId; 33 | } proxyFlag; 34 | }; 35 | typedef unordered_map FlagToProxys; 36 | 37 | typedef unordered_map IDToConnects; 38 | typedef unordered_map IDToConnectProxys; 39 | 40 | 41 | class CNetMsgComm; 42 | 43 | // 连接对象管理 44 | class CConnectMgr 45 | { 46 | public: 47 | CConnectMgr(); 48 | ~CConnectMgr(); 49 | 50 | public: 51 | void setNetMsgComm(CNetMsgComm* netMsgComm); 52 | 53 | // 提供 实际网络连接对象 的保存、关闭、增删查等(应用上层)操作 54 | public: 55 | void addConnect(const string& connId, Connect* conn, void* userData = NULL); 56 | bool removeConnect(const string& connId, bool doClose = true); 57 | bool haveConnect(const string& connId); 58 | 59 | void closeConnect(const string& connId); 60 | void closeConnect(Connect* conn); 61 | 62 | Connect* getConnect(const string& connId); 63 | const IDToConnects& getConnect(); 64 | void* getUserData(Connect* conn); 65 | 66 | // 提供 连接代理对象 的保存、关闭、增删查等(应用上层)操作 67 | public: 68 | void addConnectProxy(const string& connId, ConnectProxy* conn, void* userData = NULL); 69 | bool removeConnectProxy(const string& connId, bool doClose = true, int cbFlag = 0); 70 | bool haveConnectProxy(const string& connId); 71 | 72 | bool closeConnectProxy(const string& connId, int cbFlag = 0); 73 | void closeConnectProxy(ConnectProxy* conn, int cbFlag = 0); 74 | void clearConnectProxy(); 75 | 76 | ConnectProxy* getConnectProxy(const string& connId); 77 | const IDToConnectProxys& getConnectProxy(); 78 | void* getProxyUserData(ConnectProxy* conn); 79 | 80 | 81 | // 代理操作(框架底层) 82 | public: 83 | void addProxy(uuid_type flag, ConnectProxy* conn); 84 | ConnectProxy* removeProxy(uuid_type flag); 85 | ConnectProxy* removeProxy(FlagToProxys::iterator it); 86 | void clearProxy(); 87 | bool haveProxy(uuid_type flag, FlagToProxys::iterator& it); 88 | 89 | ConnectProxy* getProxy(uuid_type flag); 90 | const FlagToProxys& getProxy(); 91 | 92 | ConnectProxy* createProxy(); 93 | void destroyProxy(ConnectProxy*& conn); 94 | 95 | 96 | private: 97 | IDToConnects m_id2Connects; 98 | IDToConnectProxys m_id2ConnectProxys; 99 | FlagToProxys m_flag2Proxys; 100 | 101 | CNetMsgComm* m_netMsgComm; 102 | 103 | CMemManager m_memForProxyData; 104 | 105 | 106 | DISABLE_COPY_ASSIGN(CConnectMgr); 107 | }; 108 | 109 | } 110 | 111 | #endif // CCONNECT_MGR_H 112 | -------------------------------------------------------------------------------- /frame/SrvFrame/CDataContent.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.07.27 4 | * description : 数据内容存储 5 | */ 6 | 7 | #ifndef CDATA_CONTENT_H 8 | #define CDATA_CONTENT_H 9 | 10 | #include 11 | #include 12 | 13 | #include "base/MacroDefine.h" 14 | #include "base/CMemManager.h" 15 | 16 | 17 | using namespace std; 18 | 19 | namespace NFrame 20 | { 21 | 22 | class CModule; 23 | 24 | static const unsigned int SrvIdLen = 16; 25 | typedef unordered_map IndexToLocalAsyncData; // 服务索引&本地异步数据 26 | 27 | // 本地异步存储的内容 28 | // 使用场景:发送异步消息后存储本地数据,等异步应答消息回来后可以方便的取出之前存储的数据 29 | class CLocalAsyncData 30 | { 31 | public: 32 | CLocalAsyncData(CModule* module, const unsigned int bufferSize, const unsigned int bufferCount); 33 | ~CLocalAsyncData(); 34 | 35 | public: 36 | char* createData(); // 创建数据缓存区,以便可以存储本地异步数据,高效率 37 | bool createData(const char* data, unsigned int len); // 创建&存储本地异步数据,多了一次数据拷贝,低效率 38 | 39 | void destroyData(const char* data = NULL); // 销毁&清空本地异步数据 40 | void destroyAllData(); // 销毁&清空所有本地异步数据 41 | 42 | public: 43 | unsigned int getBufferSize() const; // 获取数据缓存区大小容量 44 | char* getData(); // 取得本地异步数据 45 | 46 | private: 47 | void generateDataId(); 48 | 49 | private: 50 | NCommon::CMemManager m_memForData; 51 | unsigned int m_bufferSize; 52 | 53 | unsigned int m_index; 54 | IndexToLocalAsyncData m_idx2LocalAsyncData; 55 | 56 | CModule* m_module; 57 | char m_strSrvId[SrvIdLen]; 58 | unsigned int m_srvIdLen; 59 | 60 | 61 | DISABLE_CONSTRUCTION_ASSIGN(CLocalAsyncData); 62 | }; 63 | 64 | 65 | 66 | 67 | typedef unordered_map SecondKeyToData; // 二级key数据 68 | typedef unordered_map FirstKeyToMap; // 一级key数据 69 | 70 | // 本地数据存储 71 | class CDataContent 72 | { 73 | public: 74 | CDataContent(const unsigned int bufferSize, const unsigned int bufferCount); 75 | ~CDataContent(); 76 | 77 | public: 78 | char* get(int firstKey, const char* secondKey, bool isRemove = true); 79 | char* get(int firstKey, const string& secondKey, bool isRemove = true); 80 | void set(int firstKey, const char* secondKey, char* data); 81 | void set(int firstKey, const string& secondKey, char* data); 82 | 83 | SecondKeyToData* get(int firstKey); 84 | void clear(int firstKey); 85 | 86 | void remove(int firstKey, const char* secondKey); 87 | void remove(int firstKey); 88 | void removeAll(); 89 | 90 | public: 91 | char* getBuffer(); 92 | void putBuffer(char* buffer); 93 | unsigned int getBufferSize(); 94 | 95 | private: 96 | NCommon::CMemManager m_memForData; 97 | FirstKeyToMap m_firstKeyToData; 98 | 99 | 100 | DISABLE_CONSTRUCTION_ASSIGN(CDataContent); 101 | }; 102 | 103 | } 104 | 105 | #endif // CDATA_CONTENT_H 106 | -------------------------------------------------------------------------------- /frame/SrvFrame/CGameModule.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.03.27 4 | * description : 游戏逻辑开发框架API 5 | */ 6 | 7 | #include 8 | #include "CGameModule.h" 9 | #include "CService.h" 10 | #include "base/ErrorCode.h" 11 | 12 | 13 | using namespace NCommon; 14 | using namespace NErrorCode; 15 | 16 | namespace NFrame 17 | { 18 | 19 | CGameModule::CGameModule() 20 | { 21 | memset(&m_netClientContext, 0, sizeof(m_netClientContext)); 22 | m_clientProtocolHanders = &m_protocolHanders[OutsideClientServiceType]; 23 | } 24 | 25 | CGameModule::~CGameModule() 26 | { 27 | memset(&m_netClientContext, 0, sizeof(m_netClientContext)); 28 | m_clientProtocolHanders = NULL; 29 | } 30 | 31 | // 收到网络客户端的消息 32 | int CGameModule::onClientMessage(const char* msgData, const unsigned int msgLen, const unsigned int msgId, 33 | unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, Connect* conn) 34 | { 35 | if (protocolId >= MaxProtocolIDCount) 36 | { 37 | ReleaseErrorLog("receive net client msg error, serviceId = %u, protocolId = %d", serviceId, protocolId); 38 | return InvalidParam; 39 | } 40 | 41 | ProtocolIdToHandler::const_iterator handlerIt = m_clientProtocolHanders->find(protocolId); 42 | if (handlerIt == m_clientProtocolHanders->end() || handlerIt->second.handler == NULL) 43 | { 44 | ReleaseErrorLog("not find the protocol handler for net client msg, serviceId = %u, protocolId = %d", serviceId, protocolId); 45 | return NoFoundProtocolHandler; 46 | } 47 | 48 | // 填写消息上下文信息 49 | m_context.msgId = msgId; 50 | m_netClientContext.serviceId = serviceId; 51 | m_netClientContext.moduleId = moduleId; 52 | m_netClientContext.protocolId = protocolId; 53 | m_netClientContext.conn = conn; 54 | 55 | // 业务逻辑处理消息 56 | m_msgType = MessageType::NetClientMsg; 57 | (handlerIt->second.instance->*(handlerIt->second.handler))(msgData, msgLen, serviceId, moduleId, protocolId); 58 | 59 | m_context.msgId = 0; 60 | m_netClientContext.protocolId = (unsigned short)-1; 61 | m_netClientContext.conn = NULL; 62 | 63 | return Success; 64 | } 65 | 66 | // 当前网络客户端消息上下文内容 67 | const NetClientContext& CGameModule::getNetClientContext() 68 | { 69 | return m_netClientContext; 70 | } 71 | 72 | // 设置新的上下文连接对象,返回之前的连接对象 73 | Connect* CGameModule::setContextConnect(Connect* newConn) 74 | { 75 | Connect* curConn = m_netClientContext.conn; 76 | m_netClientContext.conn = newConn; 77 | return curConn; 78 | } 79 | 80 | // 向目标网络客户端发送消息 81 | int CGameModule::sendMsgToClient(const char* msgData, const unsigned int msgLen, unsigned short protocolId, unsigned int serviceId, unsigned short moduleId) 82 | { 83 | int rc = m_service->sendMsgToClient(msgData, msgLen, m_context.msgId, serviceId, moduleId, protocolId, m_netClientContext.conn); 84 | if (rc != Success) ReleaseErrorLog("send client message error1, msgLen = %u, serviceId = %d, moduleId = %d, protocolId = %d, rc = %d", msgLen, serviceId, moduleId, protocolId, rc); 85 | return rc; 86 | } 87 | 88 | int CGameModule::sendMsgToClient(const char* msgData, const unsigned int msgLen, unsigned short protocolId, 89 | const char* userName, unsigned int serviceId, unsigned short moduleId, unsigned int msgId) 90 | { 91 | if (msgId == 0) msgId = m_context.msgId; 92 | int rc = (userName != NULL) ? m_service->sendMsgToClient(msgData, msgLen, msgId, serviceId, moduleId, protocolId, getConnect(userName)) : InvalidParam; 93 | if (rc != Success) ReleaseErrorLog("send client message error2, msgLen = %u, serviceId = %d, moduleId = %d, protocolId = %d, rc = %d, userName = %s", 94 | msgLen, serviceId, moduleId, protocolId, rc, (userName != NULL) ? userName : ""); 95 | return rc; 96 | } 97 | 98 | int CGameModule::sendMsgToClient(const char* msgData, const unsigned int msgLen, unsigned short protocolId, 99 | Connect* conn, unsigned int serviceId, unsigned short moduleId, unsigned int msgId) 100 | { 101 | if (msgId == 0) msgId = m_context.msgId; 102 | int rc = m_service->sendMsgToClient(msgData, msgLen, msgId, serviceId, moduleId, protocolId, conn); 103 | if (rc != Success) ReleaseErrorLog("send client message error3, msgLen = %u, serviceId = %d, moduleId = %d, protocolId = %d, rc = %d", msgLen, serviceId, moduleId, protocolId, rc); 104 | return rc; 105 | } 106 | 107 | } 108 | 109 | -------------------------------------------------------------------------------- /frame/SrvFrame/CGameModule.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.03.27 4 | * description : 游戏逻辑开发框架API 5 | */ 6 | 7 | #ifndef CGAME_MODULE_H 8 | #define CGAME_MODULE_H 9 | 10 | #include "CNetDataHandler.h" 11 | 12 | 13 | namespace NFrame 14 | { 15 | 16 | // 网络客户端消息上下文内容 17 | struct NetClientContext 18 | { 19 | unsigned int serviceId; // 服务ID 20 | unsigned short moduleId; // 服务下的模块ID 21 | unsigned short protocolId; // 模块下的协议ID 22 | 23 | Connect* conn; // 当前消息对应的连接 24 | }; 25 | 26 | 27 | // 游戏模块开发者接口 28 | class CGameModule : public CNetDataHandler 29 | { 30 | public: 31 | CGameModule(); 32 | virtual ~CGameModule(); 33 | 34 | public: 35 | // 当前网络客户端消息上下文内容 36 | const NetClientContext& getNetClientContext(); 37 | 38 | // 设置新的上下文连接对象,返回之前的连接对象 39 | Connect* setContextConnect(Connect* newConn); 40 | 41 | public: 42 | // 向目标网络客户端发送消息 43 | int sendMsgToClient(const char* msgData, const unsigned int msgLen, unsigned short protocolId, unsigned int serviceId = 0, unsigned short moduleId = 0); 44 | int sendMsgToClient(const char* msgData, const unsigned int msgLen, unsigned short protocolId, 45 | const char* userName, unsigned int serviceId = 0, unsigned short moduleId = 0, unsigned int msgId = 0); 46 | int sendMsgToClient(const char* msgData, const unsigned int msgLen, unsigned short protocolId, 47 | Connect* conn, unsigned int serviceId = 0, unsigned short moduleId = 0, unsigned int msgId = 0); 48 | 49 | private: 50 | // 收到网络客户端的消息 51 | int onClientMessage(const char* msgData, const unsigned int msgLen, const unsigned int msgId, 52 | unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, Connect* conn); 53 | 54 | protected: 55 | NetClientContext m_netClientContext; 56 | ProtocolIdToHandler* m_clientProtocolHanders; 57 | 58 | 59 | DISABLE_COPY_ASSIGN(CGameModule); 60 | }; 61 | 62 | } 63 | 64 | #endif // CGAME_MODULE_H 65 | -------------------------------------------------------------------------------- /frame/SrvFrame/CLogicHandler.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.10.12 4 | * description : 游戏逻辑处理驱动 5 | */ 6 | 7 | #ifndef CLOGIC_HANDLER_H 8 | #define CLOGIC_HANDLER_H 9 | 10 | #include "FrameType.h" 11 | #include "CModule.h" 12 | 13 | 14 | namespace NFrame 15 | { 16 | 17 | // 网络客户端消息上下文内容 18 | struct ConnectProxyContext 19 | { 20 | unsigned int serviceId; // 服务ID 21 | unsigned short moduleId; // 服务下的模块ID 22 | unsigned short protocolId; // 模块下的协议ID 23 | 24 | ConnectProxy* conn; // 当前消息对应的连接代理 25 | }; 26 | 27 | 28 | // 游戏逻辑处理驱动(和网关代理进行消息通信) 29 | class CLogicHandler : public CModule 30 | { 31 | public: 32 | CLogicHandler(); 33 | virtual ~CLogicHandler(); 34 | 35 | 36 | public: 37 | // 当前网络客户端消息上下文内容 38 | const ConnectProxyContext& getConnectProxyContext(); 39 | 40 | // 设置新的上下文连接对象,返回之前的连接对象 41 | ConnectProxy* resetContextConnectProxy(ConnectProxy* newConn); 42 | 43 | // 停止连接代理,服务停止时调用 44 | void stopConnectProxy(); 45 | 46 | // 清理停止连接代理,服务启动时调用,比如服务异常退出,则启动前调用该函数,关闭之前的代理连接 47 | void cleanUpConnectProxy(const unsigned int proxyId[], const unsigned int len); 48 | 49 | public: 50 | // 获取代理信息 51 | uuid_type getProxyId(ConnectProxy* connProxy); 52 | ConnectProxy* getProxy(const uuid_type id); 53 | void closeProxy(const uuid_type id, int cbFlag = 0); // 服务关闭用户连接时调用 54 | 55 | void* resetProxyUserData(ConnectProxy* conn, void* userData = NULL); 56 | void* getProxyUserData(ConnectProxy* conn); 57 | 58 | public: 59 | // 向目标网络代理发送消息 60 | int sendMsgToProxy(const char* msgData, const unsigned int msgLen, unsigned short protocolId, unsigned int serviceId = 0, unsigned short moduleId = 0); 61 | int sendMsgToProxy(const char* msgData, const unsigned int msgLen, unsigned short protocolId, 62 | const char* userName, unsigned int serviceId = 0, unsigned short moduleId = 0, unsigned int msgId = 0); 63 | int sendMsgToProxy(const char* msgData, const unsigned int msgLen, unsigned short protocolId, 64 | ConnectProxy* conn, unsigned int serviceId = 0, unsigned short moduleId = 0, unsigned int msgId = 0); 65 | 66 | 67 | // 提供连接代理对象的保存、关闭、增删查等操作 68 | public: 69 | // 应用上层如果不使用框架提供的连接代理容器,则以string key类型发送消息时需要重写该接口 70 | virtual ConnectProxy* getConnectProxy(const string& connId); 71 | 72 | void addConnectProxy(const string& connId, ConnectProxy* conn, void* userData = NULL); 73 | bool removeConnectProxy(const string& connId, int cbFlag = 0, bool doClose = true); 74 | bool haveConnectProxy(const string& connId); 75 | bool closeConnectProxy(const string& connId, int cbFlag = 0); 76 | void closeConnectProxy(ConnectProxy* conn, int cbFlag = 0); 77 | const IDToConnectProxys& getConnectProxy(); 78 | bool resetProxyUserData(const string& connId, void* userData = NULL); 79 | 80 | private: 81 | // 收到连接代理的数据 82 | virtual int onProxyMessage(const char* msgData, const unsigned int msgLen, const unsigned int msgId, 83 | unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, ConnectProxy* conn); 84 | 85 | virtual void onRegister(const char* srvName, const unsigned int srvId, unsigned short moduleId); 86 | 87 | virtual bool onPreHandleMessage(const char* msgData, const unsigned int msgLen, const ConnectProxyContext& connProxyContext); 88 | 89 | 90 | private: 91 | ConnectProxyContext m_connectProxyContext; 92 | ProtocolIdToHandler* m_proxyProtocolHanders; 93 | 94 | 95 | friend class CService; 96 | 97 | 98 | DISABLE_COPY_ASSIGN(CLogicHandler); 99 | }; 100 | 101 | } 102 | 103 | #endif // CLOGIC_HANDLER_H 104 | -------------------------------------------------------------------------------- /frame/SrvFrame/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | 3 | SET(PROJECT_NAME serviceFrame) 4 | project(${PROJECT_NAME}) 5 | 6 | #包含公共头文件 7 | include(../../cmake/common.cmake) 8 | 9 | #包含当前目录所有源文件 10 | AUX_SOURCE_DIRECTORY(. ALL_SOURCES) 11 | 12 | #Generate the static library from the library sources 13 | add_library(${PROJECT_NAME} STATIC ${ALL_SOURCES}) -------------------------------------------------------------------------------- /frame/SrvFrame/CModule.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.30 4 | * description : 服务开发模块API定义实现 5 | */ 6 | 7 | #ifndef CMODULE_H 8 | #define CMODULE_H 9 | 10 | #include 11 | #include 12 | 13 | #include "IService.h" 14 | #include "CConnectMgr.h" 15 | #include "base/MacroDefine.h" 16 | #include "base/CCfg.h" 17 | 18 | 19 | namespace NFrame 20 | { 21 | 22 | // 一个模块最多支持处理 MaxProtocolIDCount 个协议 23 | // 注册的协议ID值不能大于等于 MaxProtocolIDCount 24 | static const unsigned short MaxProtocolIDCount = 8192; 25 | 26 | // 协议消息处理者 27 | class CHandler; 28 | typedef void (CHandler::*ProtocolHandler)(const char* msgData, const unsigned int msgLen, unsigned int srcSrvId, unsigned short srcModuleId, unsigned short srcProtocolId); 29 | struct MsgHandler 30 | { 31 | CHandler* instance; 32 | ProtocolHandler handler; 33 | }; 34 | 35 | typedef std::unordered_map ProtocolIdToHandler; 36 | 37 | typedef std::unordered_map ServiceTypeToProtocolHandler; 38 | 39 | 40 | // 定时器消息处理者函数 41 | typedef void (CHandler::*TimerHandler)(unsigned int timerId, int userId, void* param, unsigned int remainCount); 42 | 43 | class CHandler 44 | { 45 | public: 46 | CHandler(); 47 | virtual ~CHandler(); 48 | 49 | private: 50 | // 定时器消息 51 | void onTimeOut(TimerHandler timerHandler, unsigned int timerId, int userId, void* param, unsigned int remainCount); 52 | 53 | friend class CService; 54 | 55 | DISABLE_COPY_ASSIGN(CHandler); 56 | }; 57 | 58 | 59 | // 服务消息上下文内容 60 | struct Context 61 | { 62 | // 消息ID 63 | unsigned int msgId; 64 | 65 | // 消息源端 66 | unsigned int srcSrvId; 67 | unsigned short srcSrvType; 68 | unsigned short srcModuleId; 69 | unsigned short srcProtocolId; 70 | 71 | // 消息目标端 72 | unsigned int dstSrvId; 73 | unsigned short dstModuleId; 74 | unsigned short dstProtocolId; 75 | 76 | // 用户数据 77 | char userData[MaxUserDataLen + 1]; 78 | unsigned int userDataLen; 79 | int userFlag; 80 | 81 | // 异步数据标识 82 | char srvAsyncDataFlag[MaxLocalAsyncDataFlagLen + 1]; 83 | unsigned int srvAsyncDataFlagLen; 84 | }; 85 | 86 | 87 | class CService; 88 | 89 | // 模块开发者接口 90 | class CModule : public CHandler 91 | { 92 | public: 93 | CModule(); 94 | virtual ~CModule(); 95 | 96 | public: 97 | // 本服务信息 98 | const char* getSrvName(); 99 | unsigned short getSrvType(); 100 | unsigned int getSrvId(); 101 | unsigned short getModuleId(); 102 | 103 | // 停止退出服务 104 | void stopService(int flag = 1); 105 | 106 | // 获取服务ID,主要用于发送服务消息 107 | unsigned int getServiceId(const char* serviceName); 108 | 109 | // 当前消息上下文内容 110 | const Context& getContext(); 111 | 112 | // 注册处理协议的函数 113 | int registerProtocol(unsigned int srcSrvType, unsigned short protocolId, ProtocolHandler handler, CHandler* instance = NULL); 114 | 115 | // 向目标服务发送请求消息 116 | // handleProtocolId : 应答消息的处理协议ID,如果该消息存在应答的话 117 | int sendMessage(const char* msgData, const unsigned int msgLen, const char* userData, const unsigned int userDataLen, 118 | unsigned int dstServiceId, unsigned short dstProtocolId, unsigned short dstModuleId = 0, unsigned short handleProtocolId = 0); 119 | 120 | // 向目标服务发送请求消息 121 | // handleProtocolId : 应答消息的处理协议ID,如果该消息存在应答的话 122 | int sendMessage(const char* msgData, const unsigned int msgLen, int userFlag, const char* userData, const unsigned int userDataLen, 123 | unsigned int dstServiceId, unsigned short dstProtocolId, 124 | unsigned short dstModuleId = 0, unsigned short handleProtocolId = 0, unsigned int msgId = 0); 125 | 126 | // 向目标服务发送请求消息,默认自动发送上下文中存在的用户数据 127 | // handleProtocolId : 应答消息的处理协议ID,如果该消息存在应答的话 128 | int sendMessage(const char* msgData, const unsigned int msgLen, unsigned int dstServiceId, unsigned short dstProtocolId, 129 | unsigned short dstModuleId = 0, unsigned short handleProtocolId = 0); 130 | 131 | // 向目标服务发送请求消息,默认自动发送上下文中存在的用户数据 132 | // srcServiceProtocolId : 应答消息的处理协议ID,如果该消息存在应答的话 133 | int sendMessage(const char* msgData, const unsigned int msgLen, unsigned short srcServiceType, unsigned int srcServiceId, unsigned short srcServiceProtocolId, 134 | unsigned int dstServiceId, unsigned short dstProtocolId, unsigned short dstModuleId = 0, unsigned int msgId = 0); 135 | 136 | public: 137 | // 需要和调度线程并发加锁的,调用该函数即可 138 | // 用法如下: 139 | // CLockEx lock(setThreadMutexMode()); 140 | std::mutex* setThreadMutexMode(); // 框架调度线程和gRPC线程并发,需要加锁 141 | 142 | public: 143 | // 定时器设置,返回定时器ID,返回 0 表示设置定时器失败 144 | unsigned int setTimer(unsigned int interval, TimerHandler timerHandler, int userId = 0, void* param = NULL, unsigned int count = 1, CHandler* instance = NULL, unsigned int paramLen = 0); 145 | void* killTimer(unsigned int timerId, int* userId = NULL, unsigned int* paramLen = NULL); 146 | 147 | // 服务开发者实现的接口 148 | private: 149 | virtual void onLoad(const char* srvName, const unsigned int srvId, unsigned short moduleId); // 服务启动,做初始化工作 150 | virtual void onUnLoad(const char* srvName, const unsigned int srvId, unsigned short moduleId); // 服务停止运行,做去初始化工作 151 | virtual void onRegister(const char* srvName, const unsigned int srvId, unsigned short moduleId) = 0; // 在此注册本模块处理的协议函数,绑定协议ID到实现函数 152 | virtual void onRun(const char* srvName, const unsigned int srvId, unsigned short moduleId); // 模块开始运行 153 | 154 | 155 | private: 156 | // 加载模块 157 | void doLoad(unsigned short moduleId, const char* srvName, const unsigned int srvId, CConnectMgr* connectMgr, NCommon::CCfg* srvMsgCommCfg); 158 | 159 | // 服务模块收到消息 160 | virtual int onServiceMessage(const char* msgData, const unsigned int msgLen, const char* userData, const unsigned int userDataLen, 161 | unsigned short dstProtocolId, unsigned int srcSrvId, unsigned short srcSrvType, unsigned short srcModuleId, 162 | unsigned short srcProtocolId, int userFlag, unsigned int msgId, const char* srvAsyncDataFlag, unsigned int srvAsyncDataFlagLen); 163 | 164 | // 收到网络客户端的消息 165 | virtual int onClientMessage(const char* msgData, const unsigned int msgLen, const unsigned int msgId, 166 | unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, Connect* conn); 167 | 168 | // 收到连接代理的数据 169 | virtual int onProxyMessage(const char* msgData, const unsigned int msgLen, const unsigned int msgId, 170 | unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, ConnectProxy* conn); 171 | 172 | 173 | protected: 174 | ServiceTypeToProtocolHandler m_protocolHanders; 175 | 176 | CService* m_service; 177 | CConnectMgr* m_connectMgr; 178 | 179 | Context m_context; 180 | MessageType m_msgType; 181 | 182 | CCfg* m_srvMsgCommCfg; // 服务间消息通信配置信息 183 | 184 | private: 185 | ProtocolIdToHandler m_serviceProtocolHandler; 186 | 187 | unsigned short m_moduleId; 188 | 189 | 190 | friend class CService; 191 | 192 | DISABLE_COPY_ASSIGN(CModule); 193 | }; 194 | 195 | } 196 | 197 | #endif // CMODULE_H 198 | -------------------------------------------------------------------------------- /frame/SrvFrame/CNetDataHandler.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.06.30 4 | * description : 纯网络数据处理驱动 5 | */ 6 | 7 | #include 8 | #include "CNetDataHandler.h" 9 | #include "CService.h" 10 | #include "base/ErrorCode.h" 11 | 12 | 13 | using namespace NCommon; 14 | using namespace NErrorCode; 15 | 16 | namespace NFrame 17 | { 18 | 19 | CNetDataHandler::CNetDataHandler() 20 | { 21 | } 22 | 23 | CNetDataHandler::~CNetDataHandler() 24 | { 25 | } 26 | 27 | // 收到网络客户端的数据 28 | int CNetDataHandler::onClientMessage(const char* data, const unsigned int len, const unsigned int msgId, 29 | unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, Connect* conn) 30 | { 31 | return onClientData(conn, data, len); 32 | } 33 | 34 | int CNetDataHandler::onClientData(Connect* conn, const char* data, const unsigned int len) 35 | { 36 | return NoFoundProtocolHandler; 37 | } 38 | 39 | // 本地端主动建立的连接 40 | void CNetDataHandler::doCreateActiveConnect(ActiveConnectData* activeConnectData) 41 | { 42 | (this->*(activeConnectData->cbFunc))(activeConnectData->conn, activeConnectData->data.peerIp, activeConnectData->data.peerPort, activeConnectData->userCb, activeConnectData->data.userId); 43 | } 44 | 45 | // 业务发起主动连接调用 46 | // 本地端准备发起主动连接 47 | // peerIp&peerPort&userId 唯一标识一个主动连接,三者都相同则表示是同一个连接 48 | int CNetDataHandler::doActiveConnect(ActiveConnectHandler cbFunction, const strIP_t peerIp, unsigned short peerPort, unsigned int timeOut, void* userCb, int userId) 49 | { 50 | int rc = m_service->doActiveConnect(this, cbFunction, peerIp, peerPort, timeOut, userCb, userId); 51 | if (rc != Success) ReleaseErrorLog("do active connect error, rc = %d", rc); 52 | return rc; 53 | } 54 | 55 | // 向目标网络客户端发送数据 56 | int CNetDataHandler::sendDataToClient(Connect* conn, const char* data, const unsigned int len) 57 | { 58 | int rc = m_service->sendDataToClient(conn, data, len); 59 | if (rc != Success) ReleaseErrorLog("send client data by connect error, rc = %d, len = %d", rc, len); 60 | return rc; 61 | } 62 | 63 | int CNetDataHandler::sendDataToClient(const char* connId, const char* data, const unsigned int len) 64 | { 65 | int rc = (connId != NULL) ? m_service->sendDataToClient(getConnect(connId), data, len) : InvalidParam; 66 | if (rc != Success) ReleaseErrorLog("send client data by connId error, rc = %d, len = %d, connId = %s", rc, len, (connId != NULL) ? connId : ""); 67 | return rc; 68 | } 69 | 70 | // 应用上层如果不使用框架提供的连接容器,则以string key类型发送消息时需要重写该接口 71 | Connect* CNetDataHandler::getConnect(const string& connId) 72 | { 73 | return m_connectMgr->getConnect(connId); 74 | } 75 | 76 | void CNetDataHandler::addConnect(const string& connId, Connect* conn, void* userData) 77 | { 78 | m_connectMgr->addConnect(connId, conn, userData); 79 | } 80 | 81 | const IDToConnects& CNetDataHandler::getConnect() 82 | { 83 | return m_connectMgr->getConnect(); 84 | } 85 | 86 | void* CNetDataHandler::resetUserData(Connect* conn, void* userData) 87 | { 88 | void* oldData = NULL; 89 | if (conn != NULL) 90 | { 91 | oldData = conn->userCb; 92 | conn->userCb = userData; 93 | } 94 | return oldData; 95 | } 96 | 97 | bool CNetDataHandler::resetUserData(const string& connId, void* userData) 98 | { 99 | Connect* conn = m_connectMgr->getConnect(connId); 100 | resetUserData(conn, userData); 101 | return (conn != NULL); 102 | } 103 | 104 | void* CNetDataHandler::getUserData(Connect* conn) 105 | { 106 | return m_connectMgr->getUserData(conn); 107 | } 108 | 109 | bool CNetDataHandler::removeConnect(const string& connId, bool doClose) 110 | { 111 | return m_connectMgr->removeConnect(connId, doClose); 112 | } 113 | 114 | bool CNetDataHandler::haveConnect(const string& connId) 115 | { 116 | return m_connectMgr->haveConnect(connId); 117 | } 118 | 119 | void CNetDataHandler::closeConnect(const string& connId) 120 | { 121 | m_connectMgr->closeConnect(connId); 122 | } 123 | 124 | void CNetDataHandler::closeConnect(Connect* conn) 125 | { 126 | m_connectMgr->closeConnect(conn); 127 | } 128 | 129 | void CNetDataHandler::onRegister(const char* srvName, const unsigned int srvId, unsigned short moduleId) 130 | { 131 | } 132 | 133 | } 134 | 135 | -------------------------------------------------------------------------------- /frame/SrvFrame/CNetDataHandler.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.06.30 4 | * description : 纯网络数据处理驱动 5 | */ 6 | 7 | #ifndef CNET_DATA_HANDLER_H 8 | #define CNET_DATA_HANDLER_H 9 | 10 | #include "CModule.h" 11 | #include "FrameType.h" 12 | 13 | 14 | namespace NFrame 15 | { 16 | 17 | // 纯网络数据处理驱动 18 | class CNetDataHandler : public CModule 19 | { 20 | public: 21 | CNetDataHandler(); 22 | virtual ~CNetDataHandler(); 23 | 24 | public: 25 | // 向目标网络客户端发送数据 26 | int sendDataToClient(Connect* conn, const char* data, const unsigned int len); 27 | int sendDataToClient(const char* connId, const char* data, const unsigned int len); 28 | 29 | // 提供连接对象的保存、关闭、增删查等操作 30 | public: 31 | // 应用上层如果不使用框架提供的连接容器,则以string key类型发送消息时需要重写该接口 32 | virtual Connect* getConnect(const string& connId); 33 | 34 | void addConnect(const string& connId, Connect* conn, void* userData = NULL); 35 | bool removeConnect(const string& connId, bool doClose = true); 36 | bool haveConnect(const string& connId); 37 | void closeConnect(const string& connId); 38 | void closeConnect(Connect* conn); 39 | const IDToConnects& getConnect(); 40 | void* resetUserData(Connect* conn, void* userData = NULL); 41 | bool resetUserData(const string& connId, void* userData = NULL); 42 | void* getUserData(Connect* conn); 43 | 44 | public: 45 | // 本地端准备发起主动连接 46 | // peerIp&peerPort&userId 唯一标识一个主动连接,三者都相同则表示是同一个连接 47 | int doActiveConnect(ActiveConnectHandler cbFunction, const strIP_t peerIp, unsigned short peerPort, unsigned int timeOut, void* userCb = NULL, int userId = 0); 48 | 49 | private: 50 | void doCreateActiveConnect(ActiveConnectData* activeConnectData); 51 | 52 | private: 53 | // 收到网络客户端的数据 54 | virtual int onClientMessage(const char* msgData, const unsigned int msgLen, const unsigned int msgId, 55 | unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, Connect* conn); 56 | 57 | virtual int onClientData(Connect* conn, const char* data, const unsigned int len); 58 | 59 | virtual void onRegister(const char* srvName, const unsigned int srvId, unsigned short moduleId); 60 | 61 | 62 | friend class CService; 63 | 64 | 65 | DISABLE_COPY_ASSIGN(CNetDataHandler); 66 | }; 67 | 68 | } 69 | 70 | #endif // CNET_DATA_HANDLER_H 71 | -------------------------------------------------------------------------------- /frame/SrvFrame/CNetMsgComm.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.03.11 4 | * description : 网络消息收发 5 | */ 6 | 7 | #ifndef CNETMSGCOMM_H 8 | #define CNETMSGCOMM_H 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "FrameType.h" 15 | #include "base/MacroDefine.h" 16 | #include "base/CCfg.h" 17 | #include "connect/ILogicHandler.h" 18 | 19 | 20 | using namespace std; 21 | using namespace NCommon; 22 | using namespace NConnect; 23 | 24 | namespace NFrame 25 | { 26 | 27 | // IP属性检查模式 28 | enum EIpAttributeMode 29 | { 30 | EIpNormalMode = 0, // 正常模式,不做任何过滤 31 | EIpBlackListMode = 1, // IP黑名单模式 32 | EIpWhiteListMode = 2, // IP白名单模式 33 | }; 34 | 35 | // 连接对端IP 掩码配置信息,如:183.78.168.0/22,183.78.168.77/32 36 | typedef std::unordered_set MaskIPSet; 37 | typedef std::unordered_map MaskToIPsetMap; 38 | 39 | 40 | // 逻辑层实现该接口 41 | // 使用连接管理的逻辑层实现的接口,连接管理模块调用 42 | class CNetMsgComm : public ILogicHandler 43 | { 44 | public: 45 | CNetMsgComm(); 46 | ~CNetMsgComm(); 47 | 48 | // !说明:必须先初始化成功才能开始收发消息 49 | public: 50 | int init(CCfg* msgCommCfgData, const char* srvName); 51 | void unInit(); 52 | 53 | void reLoadCfg(); // reload 本服务配置 54 | 55 | DataHandlerType getDataHandlerMode(); 56 | 57 | public: 58 | // 逻辑层直接从连接收发消息数据 59 | ReturnValue recv(Connect*& conn, char* data, unsigned int& len); 60 | ReturnValue send(Connect* conn, const char* data, const unsigned int len, bool isNeedWriteMsgHeader = true); 61 | 62 | void close(Connect* conn); 63 | 64 | 65 | private: 66 | unsigned int generateIPList(const char* ipListFileName, MaskToIPsetMap& ipList); 67 | 68 | void outputCheckIpListResult(); 69 | 70 | // 以下API为连接管理模块主动调用 71 | private: 72 | // 本地端主动创建连接 peerIp&peerPort 为连接对端的IP、端口号 73 | virtual ActiveConnect* getConnectData(); 74 | 75 | // 主动连接建立的时候调用 76 | // conn 为连接对应的数据,peerIp & peerPort 为连接对端的IP地址和端口号 77 | // 网络管理层根据逻辑层返回码判断是否需要关闭该连接,返回码为 [CloseConnect, SendDataCloseConnect] 则关闭该连接 78 | virtual ReturnValue doCreateConnect(Connect* conn, const char* peerIp, const unsigned short peerPort, ReturnValue rtVal, void*& cb); 79 | 80 | private: 81 | // 被动连接建立的时候调用 82 | // conn 为连接对应的数据,peerIp & peerPort 为连接对端的IP地址和端口号 83 | // 网络管理层根据逻辑层返回码判断是否需要关闭该连接,返回码为 [CloseConnect, SendDataCloseConnect] 则关闭该连接 84 | virtual ReturnValue onCreateConnect(Connect* conn, const char* peerIp, const unsigned short peerPort, void*& cb); 85 | 86 | virtual void onClosedConnect(Connect* conn, void* cb); // 通知逻辑层对应的逻辑连接已被关闭 87 | 88 | virtual void onInvalidConnect(const uuid_type connId, void* cb); // 通知逻辑层connLogicId对应的逻辑连接无效了,可能找不到,或者异常被关闭了,不能读写数据等等 89 | 90 | 91 | private: 92 | // 从逻辑层获取数据缓冲区,把从连接读到的数据写到该缓冲区 93 | virtual BufferHeader* getBufferHeader(); 94 | 95 | // 返回值为 (char*)-1 则表示直接丢弃该数据;返回值为非NULL则读取数据;返回值为NULL则不读取数据 96 | virtual char* getWriteBuffer(const int len, const uuid_type connId, BufferHeader* bufferHeader, void*& cb); 97 | virtual void submitWriteBuffer(char* buff, const int len, const uuid_type connId, void* cb); 98 | 99 | private: 100 | // 从逻辑层获取数据缓冲区,把该数据写入connLogicId对应的连接里 101 | virtual char* getReadBuffer(int& len, uuid_type& connId, bool& isNeedWriteMsgHeader, void*& cb); 102 | virtual void submitReadBuffer(char* buff, const int len, const uuid_type connId, void* cb); 103 | 104 | 105 | private: 106 | // 直接从从逻辑层读写消息数据,多了一次中间数据拷贝,性能较低 107 | virtual ReturnValue readData(char* data, int& len, uuid_type& connId); 108 | virtual ReturnValue writeData(const char* data, const int len, const uuid_type connId); 109 | 110 | 111 | private: 112 | // 设置连接收发数据接口对象 113 | virtual void setConnMgrInstance(IConnectMgr* instance); 114 | 115 | private: 116 | // 检查连接对端的IP是否合法,IP地址白名单&黑名单使用 117 | virtual ReturnValue checkPeerIp(unsigned int peerIp); 118 | 119 | 120 | private: 121 | IConnectMgr* m_dataHandler; 122 | DataHandlerType m_handlerMode; 123 | 124 | int m_ipAttributeMode; 125 | MaskToIPsetMap m_whiteListIP; 126 | MaskToIPsetMap m_blackListIP; 127 | 128 | 129 | DISABLE_COPY_ASSIGN(CNetMsgComm); 130 | }; 131 | 132 | } 133 | 134 | #endif // CNETMSGCOMM_H 135 | -------------------------------------------------------------------------------- /frame/SrvFrame/CService.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.30 4 | * description : 服务开发API定义实现 5 | */ 6 | 7 | #ifndef CSERVICE_H 8 | #define CSERVICE_H 9 | 10 | #include 11 | #include 12 | 13 | #include "IService.h" 14 | #include "FrameType.h" 15 | #include "CNetMsgComm.h" 16 | #include "CConnectMgr.h" 17 | #include "base/MacroDefine.h" 18 | #include "base/CMemManager.h" 19 | #include "base/CMessageQueue.h" 20 | #include "base/CTimer.h" 21 | #include "messageComm/ISrvMsgComm.h" 22 | 23 | 24 | namespace NFrame 25 | { 26 | 27 | class CHandler; 28 | class CModule; 29 | struct ServiceMsgHeader; 30 | 31 | typedef std::unordered_map TimerIdToMsg; 32 | 33 | // 定时器触发 34 | class CTimerCallBack : public NCommon::CTimerI 35 | { 36 | public: 37 | virtual bool OnTimer(unsigned int timerId, void* pParam, unsigned int remainCount); 38 | 39 | public: 40 | NCommon::CAddressQueue* pTimerMsgQueue; 41 | }; 42 | 43 | 44 | // 服务框架基础功能 45 | class CService 46 | { 47 | public: 48 | CService(); 49 | ~CService(); 50 | 51 | public: 52 | // 启动服务,初始化服务数据 53 | // cfgFile : 本服务的配置文件路径名 54 | // srvMsgCommCfgFile : 服务通信消息中间件配置文件路径名 55 | // 本服务名称 56 | int start(const char* cfgFile, const char* srvMsgCommCfgFile, const char* srvName); 57 | 58 | // 运行服务,开始收发处理消息 59 | void run(); 60 | 61 | // 停止服务 62 | void stop(int flag = 1); 63 | 64 | // 通知配置更新 65 | void notifyUpdateConfig(); 66 | 67 | public: 68 | // 向目标服务发送请求消息 69 | // handleProtocolId : 应答消息的处理协议ID,如果该消息存在应答的话 70 | int sendMessage(const char* msgData, const unsigned int msgLen, const char* userData, const unsigned int userDataLen, const char* srvAsyncDataFlag, const unsigned int srvAsyncDataFlagLen, 71 | unsigned int dstServiceId, unsigned short dstProtocolId, unsigned short dstModuleId = 0, unsigned short srcModuleId = 0, 72 | unsigned short handleProtocolId = 0, int userFlag = 0, unsigned int msgId = 0); 73 | 74 | // handleProtocolId : 应答消息的处理协议ID,如果该消息存在应答的话(用于转发消息,替换源消息的服务类型及服务ID,使得目标服务直接回消息给源端而不是中转服务) 75 | int sendMessage(const unsigned short srcServiceType, const unsigned int srcServiceId, const char* msgData, const unsigned int msgLen, const char* userData, const unsigned int userDataLen, 76 | const char* srvAsyncDataFlag, const unsigned int srvAsyncDataFlagLen, unsigned int dstServiceId, unsigned short dstProtocolId, unsigned short dstModuleId = 0, 77 | unsigned short srcModuleId = 0, unsigned short handleProtocolId = 0, int userFlag = 0, unsigned int msgId = 0); 78 | 79 | // 向目标网络客户端发送消息 80 | int sendMsgToClient(const char* msgData, const unsigned int msgLen, unsigned int msgId, unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, Connect* conn); 81 | 82 | // 向目标网络客户端发送任意数据 83 | int sendDataToClient(Connect* conn, const char* data, const unsigned int len); 84 | 85 | // 向目标连接代理发送消息 86 | int sendMsgToProxy(const char* msgData, const unsigned int msgLen, unsigned int msgId, unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, ConnectProxy* conn); 87 | 88 | public: 89 | // 主动关闭、停止连接代理 90 | void closeProxy(ConnectProxy* conn, bool isActive, int cbFlag = 0); // 服务关闭用户连接时调用 91 | void closeProxy(const uuid_type id, bool isActive, int cbFlag = 0); // 服务关闭用户连接时调用 92 | 93 | uuid_type getProxyId(ConnectProxy* connProxy); 94 | ConnectProxy* getProxy(const uuid_type id); 95 | 96 | void stopProxy(); // 服务停止时调用 97 | void cleanUpProxy(const unsigned int proxyId[], const unsigned int len); // 服务启动时调用 98 | 99 | public: 100 | const char* getName(); 101 | unsigned short getType(); 102 | unsigned int getId(); 103 | unsigned int getServiceId(const char* serviceName); 104 | 105 | int registerModule(unsigned short moduleId, CModule* pInstance); 106 | int registerNetModule(CNetDataHandler* pInstance); 107 | 108 | void setServiceType(unsigned int srvType); 109 | void setConnectClient(); 110 | 111 | void setGatewayServiceMode(bool isGatewayMode); 112 | 113 | public: 114 | // 需要和调度线程并发加锁的,调用该函数即可 115 | // 用法如下: 116 | // CLockEx lock(setThreadMutexMode()); 117 | std::mutex* setThreadMutexMode(); // 框架调度线程和gRPC线程并发,需要加锁 118 | 119 | public: 120 | // 定时器设置,返回定时器ID,返回 0 表示设置定时器失败 121 | unsigned int setTimer(CHandler* handler, unsigned int interval, TimerHandler cbFunc, int userId = 0, void* param = NULL, unsigned int count = 1, unsigned int paramLen = 0); 122 | void* killTimer(unsigned int timerId, int* userId = NULL, unsigned int* paramLen = NULL); 123 | 124 | public: 125 | // 本地端准备发起主动连接 126 | int doActiveConnect(CNetDataHandler* instance, ActiveConnectHandler cbFunction, const strIP_t peerIp, unsigned short peerPort, unsigned int timeOut, void* userCb = NULL, int userId = 0); 127 | 128 | public: 129 | void createdClientConnect(Connect* conn, const char* peerIp, const unsigned short peerPort); 130 | ActiveConnect* getActiveConnectData(); 131 | void doCreateServiceConnect(Connect* conn, const char* peerIp, const unsigned short peerPort, ReturnValue rtVal, void*& cb); 132 | void closedClientConnect(Connect* conn); 133 | 134 | private: 135 | void handleServiceMessage(ServiceMsgHeader* msgHeader, unsigned int msgLen); 136 | void handleClientMessage(const char* data, Connect* conn, unsigned int msgLen); 137 | void handleClientMessage(ClientMsgHeader* msgHeader, Connect* conn, unsigned int msgLen); 138 | bool handleTimerMessage(); 139 | void clear(); 140 | 141 | private: 142 | int m_runFlag; // 服务运行标志,值0:服务运行,其他值:服务停止 143 | bool m_isNotifyUpdateConfig; 144 | const char* m_srvName; 145 | unsigned int m_srvId; 146 | unsigned short m_srvType; // 服务类型 147 | NMsgComm::ISrvMsgComm* m_srvMsgComm; 148 | char m_recvMsg[MaxMsgLen]; 149 | char m_sndMsg[MaxMsgLen]; 150 | CModule* m_moduleInstance[MaxModuleIDCount]; // 服务注册的模块实例 151 | CNetMsgComm* m_netMsgComm; // 外部客户端通信 152 | CConnectMgr m_connectMgr; // 连接管理对象 153 | 154 | unsigned int m_timerMsgMaxCount; // 支持设置的定时器最大个数,0则无限制 155 | CTimerCallBack m_timerMsgCb; // 定时器触发回调接口 156 | TimerIdToMsg m_timerIdToMsg; // kill定时器时删除定时器消息 157 | NCommon::CMemManager m_memForTimerMsg; // 定时器消息产生 158 | NCommon::CAddressQueue m_timerMsgQueue; // 定时器消息队列 159 | NCommon::CAddressQueue m_closedClientConnectQueue; // 关闭网络客户端连接操作队列 160 | NCommon::CAddressQueue m_activeConnectDataQueue; // 本地端主动发起建立连接的队列 161 | NCommon::CAddressQueue m_activeConnectResultQueue; // 本地端主动发起建立连接的结果 162 | NCommon::CMemManager m_memForActiveConnect; // 主动连接数据 163 | NCommon::CTimer m_timer; // 定时器各种操作 164 | bool m_gatewayServiceMode; // 目标服务收到网关服务的消息时,是否使用网关代理模式 165 | 166 | std::mutex* m_mutex; // 框架调度线程和gRPC线程并发,需要加锁 167 | 168 | DISABLE_COPY_ASSIGN(CService); 169 | }; 170 | 171 | } 172 | 173 | #endif // CSERVICE_H 174 | -------------------------------------------------------------------------------- /frame/SrvFrame/FrameType.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.30 4 | * description : 服务开发框架各个类型定义 5 | */ 6 | 7 | #ifndef FRAMETYPE_H 8 | #define FRAMETYPE_H 9 | 10 | #include "connect/ILogicHandler.h" 11 | 12 | 13 | namespace NFrame 14 | { 15 | /* SERVICE_LOGIN_GAME.proto 文件 16 | // 用户在线&离线状态 17 | enum EUserQuitStatus 18 | { 19 | EUserStatusInvalid = 0; // 无效值 20 | 21 | EUserOnline = 1; // 正常在线 22 | 23 | EUserPassiveOffline = 2; // 被动关闭连接,下线 24 | 25 | EUserChangeRoom = 3; // 玩家更换房间,下线 26 | EUserBeForceOffline = 4; // 玩家被强制下线 27 | EUserRepeateLogin = 5; // 重复登录被关闭连接,下线 28 | EUserInvalidMessage = 6; // 非法消息被关闭连接,下线 29 | EUserRepeateConnect = 7; // 重复连接被关闭,下线 30 | EUserPromptLeaveRoom = 8; // 房间提示玩家离开,连接被关闭,下线 31 | EUserBeKicked = 9; // 玩家被后台踢下线 32 | 33 | EUserInvalidService = 10; // 网关收到非目标服务(比如内部公共服务)的非法消息,关闭连接 34 | EUserOversizedMessage = 11; // 网关收到非法超大消息包,关闭连接 35 | EUserFrequentMessage = 12; // 网关频繁过度收到大量客户端消息,关闭连接 36 | EServiceFrequentMessage = 13; // 网关频繁过度收到大量服务端消息,关闭连接 37 | EGatewayServiceStop = 14; // 网关服务停止,关闭连接 38 | 39 | EServiceStart = 100; // 服务启动(EServiceStatus::ESrvOnline),下线 40 | EServiceStop = 101; // 服务停止(EServiceStatus::ESrvOffline),下线 41 | EServiceFault = 102; // 服务发生故障(EServiceStatus::ESrvFaultStop),要求停止相关服务 42 | 43 | ELoginErrorBase = 10000; // 大厅登录失败 44 | 45 | EUserOffline = 1000000; // 正常离线(排序原因,因此定义为最大值) 46 | } 47 | */ 48 | 49 | enum ConnectProxyOperation 50 | { 51 | ProxyException = -1, // 代理服务异常 52 | 53 | // 其值定义和业务上层保持一致,不能冲突 54 | // 参考 proto 协议 EUserQuitStatus 定义(用户在线&离线状态) 55 | ActiveClosed = 1, // 服务端主动要求关闭代理的连接 56 | PassiveClosed = 2, // 代理的连接已经被动关闭了 57 | StopProxy = 3, // 服务已经停止了,代理该服务的所有连接都将被关闭 58 | 59 | InvalidService = 10, // 网关收到非目标服务(比如内部公共服务)的非法消息,关闭连接 60 | OversizedMessage = 11, // 网关收到非法超大消息包,关闭连接 61 | ClientFrequentMessage = 12, // 网关频繁过度收到大量客户端消息,关闭连接 62 | ServiceFrequentMessage = 13, // 网关频繁过度收到大量服务端消息,关闭连接 63 | GatewayServiceStop = 14, // 网关服务停止,关闭连接 64 | }; 65 | 66 | 67 | // 客户端连接的地址 68 | struct ConnectAddress 69 | { 70 | struct in_addr peerIp; // 客户端连接对端的ip 71 | unsigned short peerPort; // 客户端连接对端的端口号 72 | }; 73 | 74 | // 连接代理数据 75 | struct ConnectProxy 76 | { 77 | int proxyFlag; // 连接代理标识符 78 | unsigned int proxyId; // 代理服务的ID 79 | 80 | void* userCb; // 用户挂接的回调数据 81 | int userId; // 用户挂接的ID 82 | 83 | struct in_addr peerIp; // 客户端连接对端的ip 84 | unsigned short peerPort; // 客户端连接对端的端口号 85 | }; 86 | 87 | // 定时器消息处理者函数 88 | class CHandler; 89 | typedef void (CHandler::*TimerHandler)(unsigned int timerId, int userId, void* param, unsigned int remainCount); 90 | 91 | class CNetDataHandler; 92 | typedef void (CNetDataHandler::*ActiveConnectHandler)(NConnect::Connect* conn, const char* peerIp, const unsigned short peerPort, void* userCb, int userId); 93 | 94 | 95 | // 外部客户端消息头部数据,注意字节对齐 96 | #pragma pack(1) 97 | struct ClientMsgHeader 98 | { 99 | unsigned int checksum; // 校验这个字段之后数据的完整性 100 | 101 | unsigned int sequence; // 序列号,防止重复包攻击 102 | unsigned int serviceId; // 服务ID 103 | unsigned short moduleId; // 服务下的模块ID 104 | unsigned short protocolId; // 模块下的协议ID 105 | unsigned int msgId; // 消息ID 106 | unsigned int msgLen; // 消息码流长度,不包含消息头长度 107 | }; 108 | #pragma pack() 109 | 110 | 111 | // 服务消息处理者标识符 112 | struct MsgHandlerID 113 | { 114 | unsigned int serviceId; // 服务ID 115 | unsigned short serviceType; // 服务类型 116 | unsigned short moduleId; // 服务下的模块ID 117 | unsigned short protocolId; // 模块下的协议ID 118 | }; 119 | 120 | // 注意字节对齐 121 | #pragma pack(1) 122 | struct ServiceMsgHeader 123 | { 124 | MsgHandlerID srcService; // 消息源服务 125 | MsgHandlerID dstService; // 消息目标服务 126 | unsigned int msgId; // 消息ID 127 | int userFlag; // 用户携带的标志数据 128 | unsigned int userDataLen; // 用户数据长度 129 | unsigned int msgLen; // 消息码流长度,不包含消息头长度 130 | unsigned int asyncDataFlagLen; // 异步数据标识长度 131 | }; 132 | #pragma pack() 133 | 134 | // 定时器消息 135 | struct TimerMessage 136 | { 137 | unsigned int timerId; // 定时器ID 138 | unsigned int count; // 剩余触发次数 139 | CHandler* handler; // 定时器消息处理者 140 | TimerHandler cbFunc; // 回调函数 141 | void* param; // 用户设置的数据 142 | unsigned int paramLen; // 用户设置的数据长度,存在长度时定时器将创建内存空间存储用户数据 143 | unsigned int userId; // 用户设置的ID 144 | unsigned int deleteRef; // 删除消息的引用计数 145 | }; 146 | 147 | // 主动连接数据 148 | struct ActiveConnectData 149 | { 150 | NConnect::ActiveConnect data; // 用户传递的连接主机的参数值 151 | void* userCb; // 用户传递的回调数据 152 | ActiveConnectHandler cbFunc; // 用户传递的回调函数 153 | CNetDataHandler* instance; // 目标处理对象 154 | NConnect::Connect* conn; // 新建立的连接数据 155 | }; 156 | } 157 | 158 | #endif // FRAMETYPE_H 159 | -------------------------------------------------------------------------------- /frame/SrvFrame/IService.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.30 4 | * description : 服务开发接口 5 | */ 6 | 7 | #ifndef ISERVICE_H 8 | #define ISERVICE_H 9 | 10 | #include "UserType.h" 11 | #include "base/MacroDefine.h" 12 | 13 | 14 | namespace NConnect 15 | { 16 | struct Connect; 17 | } 18 | 19 | namespace NFrame 20 | { 21 | 22 | class CModule; 23 | class CNetDataHandler; 24 | 25 | 26 | // 服务基础能力框架 27 | class IService 28 | { 29 | public: 30 | IService(unsigned int srvType, bool isConnectClient = false); 31 | virtual ~IService(); 32 | 33 | public: 34 | // 获取本服务名&ID 35 | const char* getName(); 36 | unsigned int getId(); 37 | 38 | // 注册本服务的各模块实例对象 39 | int registerModule(unsigned short moduleId, CModule* pInstance); 40 | 41 | // 注册纯网络数据处理模块实例对象 42 | int registerNetModule(CNetDataHandler* pInstance); 43 | 44 | // 停止退出服务 45 | void stopService(int flag = 1); 46 | 47 | // 设置是否使用网关代理模式(目标服务收到网关服务的消息时,是否使用网关代理模式) 48 | void setGatewayServiceMode(bool isGatewayMode); 49 | 50 | // 开发者实现接口 51 | public: 52 | virtual int onInit(const char* name, const unsigned int id); // 服务启动时被调用 53 | virtual void onUnInit(const char* name, const unsigned int id); // 服务停止时被调用 54 | virtual void onRegister(const char* name, const unsigned int id) = 0; // 服务启动后被调用,服务需在此注册本服务的各模块信息 55 | virtual void onUpdateConfig(const char* name, const unsigned int id); // 服务配置更新 56 | virtual int onHandle(); // 服务自己的处理逻辑 57 | 58 | public: 59 | // 收到外部数据之后调用 onReceiveMessage 60 | // 发送外部数据之前调用 onSendMessage 61 | // 一般用于数据加密&解密 62 | virtual int onReceiveMessage(NConnect::Connect* conn, char* msg, unsigned int& len); 63 | virtual int onSendMessage(NConnect::Connect* conn, char* msg, unsigned int& len); 64 | 65 | public: 66 | virtual void onClosedConnect(void* userData); // 通知逻辑层对应的连接已被关闭 67 | virtual void onCloseConnectProxy(void* userData, int cbFlag); // 通知逻辑层对应的逻辑连接代理已被关闭 68 | 69 | 70 | DISABLE_COPY_ASSIGN(IService); 71 | }; 72 | 73 | 74 | // 注册&去注册服务实例 75 | class CRegisterService 76 | { 77 | public: 78 | CRegisterService(IService* pSrvInstance); 79 | ~CRegisterService(); 80 | 81 | DISABLE_CONSTRUCTION_ASSIGN(CRegisterService); 82 | }; 83 | 84 | 85 | // 注册服务实例宏定义 86 | #define REGISTER_SERVICE(SERVICE_CLASS_NAME) \ 87 | static SERVICE_CLASS_NAME serviceInstance; \ 88 | static CRegisterService registerService(&serviceInstance) 89 | 90 | } 91 | 92 | #endif // ISERVICE_H 93 | -------------------------------------------------------------------------------- /frame/SrvFrame/UserType.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.30 4 | * description : 服务开发用户数据类型 5 | */ 6 | 7 | #ifndef USER_TYPE_H 8 | #define USER_TYPE_H 9 | 10 | #include "FrameType.h" 11 | 12 | 13 | namespace NFrame 14 | { 15 | 16 | // 一个服务最多支持 MaxModuleIDCount 个模块 17 | // 注册的模块ID不能大于等于 MaxModuleIDCount 的值 18 | static const unsigned int MaxModuleIDCount = 8; 19 | 20 | 21 | // 纯网络数据处理者注册的对应模块ID 22 | static const unsigned int NetDataHandleModuleID = MaxModuleIDCount - 1; 23 | 24 | 25 | static const unsigned int MaxUserDataLen = 32; // 支持的用户数据最大长度不能超过 MaxUserDataLen 26 | static const unsigned int MaxLocalAsyncDataFlagLen = 128; // 支持的本地异步数据标识最大长度不能超过 MaxLocalAsyncDataFlagLen 27 | static const unsigned int MaxMsgLen = 1024.00 * 1024.00 * 1.20; // 支持的消息最大长度不能超过 MaxMsgLen 28 | 29 | 30 | static const unsigned int MsgHeaderLen = sizeof(ServiceMsgHeader); 31 | static const unsigned int ClientMsgHeaderLen = sizeof(ClientMsgHeader); 32 | static const unsigned int MaxMsgLength = MaxMsgLen - MsgHeaderLen - MaxUserDataLen - MaxLocalAsyncDataFlagLen; 33 | 34 | 35 | // 框架内置的服务类型 36 | static const unsigned int CommonServiceType = 0; // 公共服务类型 37 | static const unsigned int GatewayServiceType = 1; // 网关服务类型 38 | static const unsigned int OutsideClientServiceType = 2; // 外部客户端类型 39 | 40 | 41 | // 消息类型 42 | enum MessageType 43 | { 44 | InnerServiceMsg = 0, // 内部服务器间消息 45 | NetClientMsg = 1, // 网络客户端过来的消息 46 | ConnectProxyMsg = 2, // 连接代理数据 47 | }; 48 | 49 | } 50 | 51 | #endif // USER_TYPE_H 52 | -------------------------------------------------------------------------------- /frame/SrvFrame/readme: -------------------------------------------------------------------------------- 1 | service frame code,开发框架库(消息调度处理、自动连接管理、服务开发、游戏框架、服务间消息收发、消息通信等等)代码实现。 2 | -------------------------------------------------------------------------------- /frame/SrvMsgComm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | 3 | SET(PROJECT_NAME SrvMsgComm) 4 | project(${PROJECT_NAME}) 5 | 6 | #包含公共头文件 7 | include(../../cmake/common.cmake) 8 | 9 | #包含当前目录所有源文件 10 | AUX_SOURCE_DIRECTORY(. ALL_SOURCES) 11 | 12 | #生成二进制文件 13 | add_executable(${PROJECT_NAME} ${ALL_SOURCES}) 14 | TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${MY_LIBRARY_LIST}) -------------------------------------------------------------------------------- /frame/SrvMsgComm/CNetMsgHandler.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.19 4 | * description : 网络消息收发处理 5 | */ 6 | 7 | #ifndef CNETMSGHANDLER_H 8 | #define CNETMSGHANDLER_H 9 | 10 | #include "messageComm/MsgCommType.h" 11 | #include "base/MacroDefine.h" 12 | #include "base/CMemManager.h" 13 | #include "connect/ILogicHandler.h" 14 | 15 | 16 | using namespace NCommon; 17 | using namespace NConnect; 18 | 19 | namespace NMsgComm 20 | { 21 | 22 | // 逻辑层实现该接口 23 | // 使用连接管理的逻辑层实现的接口,连接管理模块调用 24 | class CNetMsgHandler : public ILogicHandler 25 | { 26 | public: 27 | CNetMsgHandler(ShmData* shmData, CfgData* cfgData); 28 | ~CNetMsgHandler(); 29 | 30 | private: 31 | // 获取当前节点对应消息处理者的目标队列,写入网络消息 32 | MsgQueueList* getNodeMsgQueue(const unsigned int readerId); 33 | 34 | // 获取当前节点消息处理者发往外部网络节点的消息队列 35 | MsgQueueList* getNetMsgQueue(uuid_type& connId); 36 | MsgQueueList* getNetHandlerMsgQueue(uuid_type& connId); 37 | 38 | private: 39 | void onRemoveConnect(void* cb); 40 | 41 | 42 | // 以下API为连接管理模块主动调用 43 | private: 44 | // 本地端主动创建连接 peerIp&peerPort 为连接对端的IP、端口号 45 | // peerPort : 必须大于2000,防止和系统端口号冲突 46 | // timeOut : 最长timeOut秒后连接还没有建立成功则关闭,并回调返回创建连接超时;单位秒 47 | virtual ActiveConnect* getConnectData(); 48 | 49 | // 主动连接建立的时候调用 50 | // conn 为连接对应的数据,peerIp&peerPort 为连接对端的IP地址和端口号 51 | // rtVal : 返回连接是否创建成功 52 | // 网络管理层根据逻辑层返回码判断是否需要关闭该连接,返回码为 [CloseConnect, SendDataCloseConnect] 则关闭该连接 53 | virtual ReturnValue doCreateConnect(Connect* conn, const char* peerIp, const unsigned short peerPort, ReturnValue rtVal, void*& cb); 54 | 55 | 56 | private: 57 | // 被动连接建立的时候调用 58 | // conn 为连接对应的数据,peerIp & peerPort 为连接对端的IP地址和端口号 59 | // 网络管理层根据逻辑层返回码判断是否需要关闭该连接,返回码为 [CloseConnect, SendDataCloseConnect] 则关闭该连接 60 | virtual ReturnValue onCreateConnect(Connect* conn, const char* peerIp, const unsigned short peerPort, void*& cb); 61 | 62 | private: 63 | virtual void onClosedConnect(Connect* conn, void* cb); // 通知逻辑层对应的逻辑连接已被关闭 64 | virtual void onInvalidConnect(const uuid_type connId, void* cb); // 通知逻辑层connId对应的逻辑连接无效了,可能找不到,或者异常被关闭了,不能读写数据等等 65 | 66 | 67 | private: 68 | // 从逻辑层获取数据缓冲区,把从连接读到的数据写到该缓冲区 69 | // 返回NULL值则不会读取数据;返回非NULL值则先从连接缓冲区读取len的数据长度,做为getWriteBuffer接口的bufferHeader输入参数 70 | // 该接口一般做为先读取消息头部,用于解析消息头部使用 71 | virtual BufferHeader* getBufferHeader(); 72 | 73 | // 返回值为 (char*)-1 则表示直接丢弃该数据;返回值为非NULL则读取数据;返回值为NULL则不读取数据 74 | virtual char* getWriteBuffer(const int len, const uuid_type connId, BufferHeader* bufferHeader, void*& cb); 75 | virtual void submitWriteBuffer(char* buff, const int len, const uuid_type connId, void* cb); 76 | 77 | private: 78 | // 从逻辑层获取数据缓冲区,把该数据写入connLogicId对应的连接里 79 | // isNeedWriteMsgHeader 是否需要写入网络数据消息头部信息,默认会写消息头信息 80 | // isNeedWriteMsgHeader 如果逻辑层调用者填值为false,则调用者必须自己写入网络消息头部数据,即返回的可读buff中已经包含了网络消息头数据 81 | virtual char* getReadBuffer(int& len, uuid_type& connId, bool& isNeedWriteMsgHeader, void*& cb); 82 | virtual void submitReadBuffer(char* buff, const int len, const uuid_type connId, void* cb); 83 | 84 | 85 | private: 86 | // 直接从从逻辑层读写消息数据,多了一次中间数据拷贝,性能较低 87 | virtual ReturnValue readData(char* data, int& len, uuid_type& connId); 88 | virtual ReturnValue writeData(const char* data, const int len, const uuid_type connId); 89 | 90 | 91 | private: 92 | // 设置连接收发数据接口对象 93 | virtual void setConnMgrInstance(IConnectMgr* instance); 94 | 95 | 96 | private: 97 | char* m_shmAddr; 98 | ShmData* m_shm; 99 | CfgData* m_cfg; 100 | 101 | MsgQueueList** m_nodeMsgQueueList; 102 | MsgHandlerList** m_netMsgHandlers; 103 | unsigned int m_curNetHandlerIdx; 104 | QueueIndex m_curNetQueueIdx; 105 | 106 | CMemManager* m_memForActiveConn; 107 | ActiveConnect* m_activeConnects; 108 | 109 | NetMsgHeader m_netMsgHeader; 110 | BufferHeader m_buffHeader; 111 | 112 | 113 | DISABLE_CONSTRUCTION_ASSIGN(CNetMsgHandler); 114 | }; 115 | 116 | } 117 | 118 | 119 | #endif // CNETMSGHANDLER_H 120 | 121 | -------------------------------------------------------------------------------- /frame/SrvMsgComm/CSrvMsgComm.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.15 4 | * description : 各服务间消息通信中间件 5 | */ 6 | 7 | #ifndef CSRVMSGCOMM_H 8 | #define CSRVMSGCOMM_H 9 | 10 | #include "messageComm/MsgCommType.h" 11 | #include "base/MacroDefine.h" 12 | 13 | 14 | using namespace NCommon; 15 | 16 | namespace NMsgComm 17 | { 18 | 19 | class CSrvMsgComm 20 | { 21 | public: 22 | CSrvMsgComm(); 23 | ~CSrvMsgComm(); 24 | 25 | public: 26 | int createShm(const char* cfgFile); 27 | void run(); 28 | void updateConfig(); 29 | 30 | private: 31 | int getNetNodes(unsigned int& nodeCount); 32 | int initCfgFile(const char* cfgFile = NULL); 33 | int initShm(); 34 | void initNetHandler(); 35 | int initSharedMutex(); 36 | void unInitSharedMutex(); 37 | 38 | private: 39 | ShmData* m_shmData; 40 | CfgData m_cfgData; 41 | int m_keyFileFd; 42 | 43 | DISABLE_COPY_ASSIGN(CSrvMsgComm); 44 | }; 45 | 46 | } 47 | 48 | #endif // CSRVMSGCOMM_H 49 | -------------------------------------------------------------------------------- /frame/SrvMsgComm/readme: -------------------------------------------------------------------------------- 1 | node message send & recieve service,消息中间件服务(不同网络节点间自动传递收发消息)代码实现。 2 | -------------------------------------------------------------------------------- /frame/messageComm/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | 3 | SET(PROJECT_NAME messageComm) 4 | project(${PROJECT_NAME}) 5 | 6 | #包含公共头文件 7 | include(../../cmake/common.cmake) 8 | 9 | #包含当前目录所有源文件 10 | AUX_SOURCE_DIRECTORY(. ALL_SOURCES) 11 | 12 | #Generate the static library from the library sources 13 | add_library(${PROJECT_NAME} STATIC ${ALL_SOURCES}) -------------------------------------------------------------------------------- /frame/messageComm/CMsgComm.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.22 4 | * description : 共享内存服务间消息通信 5 | */ 6 | 7 | #ifndef CMSGCOMM_H 8 | #define CMSGCOMM_H 9 | 10 | #include "MsgCommType.h" 11 | #include "ISrvMsgComm.h" 12 | #include "base/MacroDefine.h" 13 | #include "base/Constant.h" 14 | #include "connect/NetType.h" 15 | 16 | 17 | using namespace NConnect; 18 | 19 | namespace NMsgComm 20 | { 21 | 22 | static const unsigned int MaxServiceId = 100000; // 服务实例的ID值必须大于0并且小于 MaxServiceId 的值 23 | 24 | 25 | // 自动加解共享锁Helper 26 | class CSharedLockGuard 27 | { 28 | public: 29 | CSharedLockGuard(SharedMutex& sharedMutex) : rSharedMutex(sharedMutex) 30 | { 31 | Success = pthread_mutex_lock(&rSharedMutex.mutex); 32 | } 33 | 34 | ~CSharedLockGuard() 35 | { 36 | if (Success == 0) pthread_mutex_unlock(&rSharedMutex.mutex); 37 | } 38 | 39 | int Success; 40 | 41 | private: 42 | SharedMutex& rSharedMutex; 43 | 44 | DISABLE_CONSTRUCTION_ASSIGN(CSharedLockGuard); 45 | }; 46 | 47 | 48 | // 服务间网络消息头部数据 49 | struct SrvMsgHeader 50 | { 51 | NetPkgHeader netPkgHeader; // 网络层数据包头部 52 | NetMsgHeader netMsgHeader; // 服务间通信网络消息头部 53 | }; 54 | 55 | 56 | class CMsgComm : public ISrvMsgComm 57 | { 58 | public: 59 | // 服务间通信公共操作api 60 | static int getFileKey(const char* pathName, const char* srvName, char* fileName, int len); 61 | static int addHandlerToNode(ShmData* shmData, NodeMsgHandler*& msgHandler); // 申请共享内存块并挂接到当前节点队列 62 | static MsgQueueList* addQueueToHandler(ShmData* shmData, MsgHandlerList* msgHandler); // 申请共享内存消息队列挂接到消息处理者 63 | 64 | 65 | public: 66 | CMsgComm(const char* srvMsgCommCfgFile, const char* srvName); 67 | virtual ~CMsgComm(); 68 | 69 | public: 70 | // 必须先初始化操作成功才能收发消息 71 | virtual int init(); 72 | virtual void unInit(); 73 | virtual CCfg* getCfg(); 74 | virtual void reLoadCfg(); 75 | 76 | public: 77 | // 获取本服务名、各服务名对应的ID 78 | virtual const char* getSrvName(); 79 | virtual unsigned int getSrvId(const char* srvName); 80 | 81 | public: 82 | // 收发消息 83 | virtual int send(const unsigned int srvId, const char* data, const unsigned int len); 84 | virtual int recv(char* data, unsigned int& len); 85 | 86 | public: 87 | // 直接从缓冲区空间收消息,避免拷贝数据,效率较高 88 | virtual int beginRecv(char*& data, int& len, void*& cb); 89 | virtual void endRecv(const char* data, const int len, void* cb); 90 | 91 | private: 92 | MsgQueueList* getSrvMsgQueue(); 93 | MsgQueueList* getReceiverMsgQueue(const unsigned int readerId); 94 | 95 | private: 96 | unsigned int m_maxServiceId; 97 | unsigned int m_srvId; 98 | char m_srvName[CfgKeyValueLen]; 99 | char* m_shmAddr; 100 | ShmData* m_shmData; 101 | MsgQueueList** m_msgQueue; 102 | MsgHandlerList* m_msgHandler; 103 | QueueIndex m_curQueueIdx; 104 | CCfg* m_cfg; 105 | const Key2Value* m_srvNameId; 106 | SrvMsgHeader m_srvMsgHeader; 107 | 108 | DISABLE_CONSTRUCTION_ASSIGN(CMsgComm); 109 | }; 110 | 111 | } 112 | 113 | #endif // CMSGCOMM_H 114 | -------------------------------------------------------------------------------- /frame/messageComm/ISrvMsgComm.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.15 4 | * description : 服务消息通信开发接口 5 | */ 6 | 7 | #ifndef ISRV_MSG_COMM_H 8 | #define ISRV_MSG_COMM_H 9 | 10 | #include "base/CCfg.h" 11 | 12 | 13 | using namespace NCommon; 14 | 15 | namespace NMsgComm 16 | { 17 | 18 | // 提供给服务消息通信开发者的开发接口 19 | class ISrvMsgComm 20 | { 21 | public: 22 | virtual ~ISrvMsgComm() {}; 23 | 24 | public: 25 | // 必须先初始化操作成功才能收发消息 26 | virtual int init() = 0; 27 | virtual void unInit() = 0; 28 | virtual CCfg* getCfg() = 0; 29 | virtual void reLoadCfg() = 0; 30 | 31 | public: 32 | // 获取本服务名、各服务名对应的ID 33 | virtual const char* getSrvName() = 0; 34 | virtual unsigned int getSrvId(const char* srvName) = 0; 35 | 36 | public: 37 | // 收发消息 38 | virtual int send(const unsigned int srvId, const char* data, const unsigned int len) = 0; 39 | virtual int recv(char* data, unsigned int& len) = 0; 40 | 41 | public: 42 | // 直接从缓冲区空间收消息,避免拷贝数据,效率较高 43 | virtual int beginRecv(char*& data, int& len, void*& cb) = 0; 44 | virtual void endRecv(const char* data, const int len, void* cb) = 0; 45 | }; 46 | 47 | 48 | // 创建&销毁ISrvMsgComm对象实例 49 | // srvMsgCommCfgFile : 消息通信配置文件 50 | // srvName : 通信的本服务名称,在消息通信配置文件中配置 51 | ISrvMsgComm* createSrvMsgComm(const char* srvMsgCommCfgFile, const char* srvName); 52 | void destroySrvMsgComm(ISrvMsgComm*& instance); 53 | 54 | } 55 | 56 | #endif // ISRV_MSG_COMM_H 57 | 58 | 59 | -------------------------------------------------------------------------------- /frame/messageComm/Makefile: -------------------------------------------------------------------------------- 1 | INC_PATH := -I/usr/local/include -I../../../common 2 | #LIB_PATH := -L../../../../lib/ 3 | #LIBS := $(LIB_PATH) -lbase -lconnect 4 | 5 | CFLAGS = -static $(INC_PATH) -g -Wall -o2 -std=c++0x 6 | CC=g++ 7 | SRC=$(wildcard *.cpp) 8 | OBJ=$(addprefix ./, $(addsuffix .o, $(basename $(SRC)))) 9 | TARGET=../../../../lib/libmessageComm.a 10 | 11 | all: $(TARGET) 12 | 13 | $(TARGET): $(OBJ) 14 | $(AR) -rcs $@ $^ 15 | rm -f $(OBJ) 16 | 17 | %.o: %.c 18 | $(CC) $(CFLAGS) -o $@ -c $< 19 | 20 | %.o: %.cpp 21 | $(CC) $(CFLAGS) -o $@ -c $< 22 | 23 | clean: 24 | rm -f $(TARGET) $(OBJ) 25 | 26 | -------------------------------------------------------------------------------- /frame/messageComm/MsgCommType.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.01.15 4 | * description : 消息数据结构类型 5 | */ 6 | 7 | #ifndef MSG_COMM_TYPE_H 8 | #define MSG_COMM_TYPE_H 9 | 10 | #include 11 | #include "base/Type.h" 12 | #include "base/Constant.h" 13 | 14 | 15 | using namespace NCommon; 16 | 17 | namespace NMsgComm 18 | { 19 | 20 | // 相对共享内存头部的偏移量 21 | typedef ulong64_t BuffIndex; 22 | typedef ulong64_t QueueIndex; 23 | typedef ulong64_t HandlerIndex; 24 | 25 | 26 | // 节点状态 27 | enum NodeStatus 28 | { 29 | InitConnect = 0, 30 | NormalConnect = 1, 31 | }; 32 | 33 | // 共享内存队列信息,每块共享内存对应一个MsgQueueList 34 | struct MsgQueueList 35 | { 36 | unsigned int readerId; // 队列接收方 37 | unsigned int writerId; // 队列发送方,0为外部节点的网络数据,非0为本节点数据 38 | 39 | PkgQueue header; // 数据队列头信息 40 | BuffIndex queue; // 队列数据开始位置 41 | 42 | QueueIndex next; // 串成队列链表 43 | }; 44 | 45 | // 每个读写消息对象 46 | struct MsgHandlerList 47 | { 48 | unsigned int readerId; // 队列接收方 49 | QueueIndex readMsg; // 从此队列读消息 50 | 51 | unsigned int status; // 节点状态 52 | uuid_type connId; // 网络节点的连接ID 53 | NodeID readerNode; // 接收方所在节点,0为当前节点,非0为其他外部节点 54 | 55 | HandlerIndex next; // 串成对象链表 56 | }; 57 | 58 | typedef MsgHandlerList NodeMsgHandler; // 当前节点的消息数据 59 | typedef MsgHandlerList NetMsgHandler; // 非本节点,网络消息数据 60 | 61 | // 进程间共享锁 62 | struct SharedMutex 63 | { 64 | pthread_mutexattr_t mutexAttr; 65 | pthread_mutex_t mutex; 66 | }; 67 | 68 | // 整个共享内存数据 69 | struct ShmData 70 | { 71 | HandlerIndex nodeMsgHandlers; // 本节点已用的共享内存块,本节点进程间通信非网络消息 72 | HandlerIndex netMsgHanders; // 非本节点已用的共享内存块,本节点(主动连接)的网络消息 73 | 74 | QueueIndex msgQueueList; // 剩余可用的共享内存块 75 | HandlerIndex msgHandlerList; // 剩余可用的消息处理者对应的内存块 76 | 77 | ulong64_t msgQueueSize; // 用户配置的总共享内存大小,其值和配置大小一致则表示共享内存已经初始化可用,否则共享内存不可用 78 | SharedMutex sharedMutex; // 进程间共享锁,进程申请共享内存块的时候需要加锁 79 | }; 80 | 81 | 82 | // 网络消息头部数据 83 | struct NetMsgHeader 84 | { 85 | unsigned int readerId; // 队列接收方 86 | unsigned int writerId; // 队列发送方 87 | }; 88 | 89 | 90 | // 消息通信中间件配置信息 91 | struct CfgData 92 | { 93 | char Name[CfgKeyValueLen]; // 通信中间件实例名 94 | strIP_t IP; // 本节点IP 95 | unsigned short Port; // 本节点通信端口号 96 | unsigned int ShmSize; // 每块共享内存大小 97 | unsigned int ShmCount; // 共享内存块个数 98 | unsigned int ActiveConnectTimeOut; // 源端主动建立连接,最长等待时间,单位:秒 99 | unsigned int MaxServiceId; // 服务实例ID的最大值 100 | unsigned int NetNodeCount; // 配置了的网络节点个数 101 | unsigned int RevcMsgCount; // 服务收消息策略,即服务单次从单一共享内存通道读取消息的最大个数 102 | }; 103 | 104 | } 105 | 106 | #endif // MSG_COMM_TYPE_H 107 | -------------------------------------------------------------------------------- /frame/messageComm/readme: -------------------------------------------------------------------------------- 1 | service message send & receive,服务(进程)间收发消息API实现代码。 2 | -------------------------------------------------------------------------------- /frame/readme: -------------------------------------------------------------------------------- 1 | 开发框架库(消息调度处理、自动连接管理、服务开发、游戏框架、服务间消息收发、消息通信等等), 2 | 消息中间件服务(不同网络节点间自动传递收发消息)等多个功能组件、服务, 3 | 最后完成一套完整的服务器引擎,基于该框架引擎可开发任意的网络服务。 4 | -------------------------------------------------------------------------------- /http_base/CHttpConnectMgr.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.07.01 4 | * description : 连接管理 5 | */ 6 | 7 | #ifndef CHTTP_CONNECT_MGR_H 8 | #define CHTTP_CONNECT_MGR_H 9 | 10 | #include "base/CThread.h" 11 | #include "base/MacroDefine.h" 12 | #include "base/CMessageQueue.h" 13 | #include "connect/CSocket.h" 14 | #include "connect/CEpoll.h" 15 | #include "HttpBaseDefine.h" 16 | 17 | 18 | using namespace NCommon; 19 | using namespace NConnect; 20 | 21 | namespace NHttp 22 | { 23 | 24 | class CHttpConnectMgr : public CThread 25 | { 26 | public: 27 | CHttpConnectMgr(); 28 | ~CHttpConnectMgr(); 29 | 30 | public: 31 | int starSrv(); 32 | void stopSrv(); 33 | bool isRunning(); 34 | 35 | public: 36 | bool doHttpConnect(const char* ip, const unsigned short port, ConnectData* connData); 37 | 38 | ConnectData* receiveConnectData(); 39 | bool haveConnectData(); 40 | 41 | private: 42 | void sendConnectData(ConnectData* connData); 43 | 44 | void closeHttpConnect(ConnectData* connData); 45 | 46 | private: 47 | // http 消息调用 48 | void onActiveConnect(uint32_t eventVal, ConnectData* conn); 49 | void handleConnect(uint32_t eventVal, ConnectData* conn); 50 | 51 | void writeToConnect(ConnectData* conn); 52 | void readFromConnect(ConnectData* conn); 53 | 54 | int parseReadData(int nRead, ConnectData* conn); 55 | 56 | private: 57 | // https 消息使用 58 | void doSSLConnect(ConnectData* connData); 59 | 60 | void writeToSSLConnect(ConnectData* connData); 61 | void readFromSSLConnect(ConnectData* connData); 62 | 63 | private: 64 | virtual void run(); // 线程实现者重写run 65 | 66 | private: 67 | CSocket m_activeConnect; // 本地端主动对其他外部节点建立连接 68 | CEpoll m_epoll; // epoll IO 监听复用 69 | CAddressQueue m_dataQueue; // 连接数据队列 70 | SrvStatus m_status; // 连接服务状态 71 | 72 | 73 | DISABLE_COPY_ASSIGN(CHttpConnectMgr); 74 | }; 75 | 76 | } 77 | 78 | #endif // CHTTP_CONNECT_MGR_H 79 | -------------------------------------------------------------------------------- /http_base/CHttpData.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.11.17 4 | * description : Http 数据处理 5 | */ 6 | 7 | #ifndef CHTTP_DATA_H 8 | #define CHTTP_DATA_H 9 | 10 | #include "base/MacroDefine.h" 11 | #include "HttpBaseDefine.h" 12 | 13 | 14 | namespace NHttp 15 | { 16 | 17 | // 消息数据分析处理 18 | class CHttpDataParser 19 | { 20 | public: 21 | static int getHttpBodyLen(const char* header, const char* body, unsigned int& len); 22 | static int parseHeader(const char* data, RequestHeader& reqData); 23 | static int parseBody(const char* header, const char* body, HttpMsgBody& msgBody); 24 | 25 | public: 26 | static void parseJSONContent(const char* content, ParamKey2Value& paramKey2Value, char separ = '"', bool removeValueSpace = false, bool removeKeySpace = false); 27 | static void parseKeyToValue(const char* content, ParamKey2Value& paramKey2Value); 28 | 29 | 30 | DISABLE_CLASS_BASE_FUNC(CHttpDataParser); 31 | }; 32 | 33 | 34 | 35 | // Http消息类型 36 | enum HttpMsgType 37 | { 38 | GET = 0, 39 | POST = 1, 40 | }; 41 | 42 | 43 | // Http消息内容 44 | class CHttpMessage 45 | { 46 | public: 47 | CHttpMessage(); 48 | ~CHttpMessage(); 49 | 50 | public: 51 | void setHeaderKeyValue(const string& key, const string& value); 52 | void setHeaderKeyValue(const char* key, const char* value); 53 | 54 | public: 55 | void setContent(const string& content); 56 | void setContent(const char* content, const unsigned int len); 57 | void setContent(const char* content); 58 | 59 | protected: 60 | ParamKey2Value m_paramKey2Value; 61 | string m_content; 62 | 63 | 64 | DISABLE_COPY_ASSIGN(CHttpMessage); 65 | }; 66 | 67 | 68 | // Http消息协议请求数据对象 69 | class CHttpRequest : public CHttpMessage 70 | { 71 | public: 72 | CHttpRequest(HttpMsgType msgType); 73 | ~CHttpRequest(); 74 | 75 | public: 76 | void setMsgType(HttpMsgType msgType); 77 | 78 | public: 79 | void setParam(const string& param); 80 | void setParam(const char* param, const unsigned int len); 81 | void setParam(const char* param); 82 | 83 | public: 84 | void setParamValue(const string& key, const string& value); 85 | void setParamValue(const char* key, const char* value); 86 | 87 | public: 88 | const char* getMessage(char* buffer, unsigned int& len, const char* host, const char* url) const; 89 | 90 | private: 91 | HttpMsgType m_msgType; 92 | string m_param; 93 | 94 | 95 | DISABLE_COPY_ASSIGN(CHttpRequest); 96 | }; 97 | 98 | 99 | // Http消息协议响应数据对象 100 | class CHttpResponse : public CHttpMessage 101 | { 102 | public: 103 | CHttpResponse(); 104 | ~CHttpResponse(); 105 | 106 | public: 107 | const char* getMessage(unsigned int& len); 108 | const char* getMessage(char* buffer, unsigned int& len); 109 | 110 | private: 111 | char m_rspMsg[MaxNetBuffSize]; 112 | 113 | 114 | DISABLE_COPY_ASSIGN(CHttpResponse); 115 | }; 116 | 117 | 118 | 119 | // SSL对象操作 120 | class CSSLObject 121 | { 122 | public: 123 | static CSSLObject& getInstance(); 124 | 125 | public: 126 | SSL* createSSLInstance(); 127 | void destroySSLInstance(SSL*& instance); 128 | 129 | private: 130 | CSSLObject(); 131 | ~CSSLObject(); 132 | 133 | private: 134 | SSL_CTX* m_SSLContext; 135 | 136 | 137 | DISABLE_COPY_ASSIGN(CSSLObject); 138 | }; 139 | 140 | 141 | } 142 | 143 | #endif // CHTTP_DATA_H 144 | -------------------------------------------------------------------------------- /http_base/CHttpSrv.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.07.01 4 | * description : Http 服务简单实现 5 | */ 6 | 7 | #ifndef CHTTP_SRV_H 8 | #define CHTTP_SRV_H 9 | 10 | #include "SrvFrame/IService.h" 11 | #include "SrvFrame/CNetDataHandler.h" 12 | #include "base/CMemManager.h" 13 | 14 | #include "CHttpConnectMgr.h" 15 | #include "CHttpData.h" 16 | #include "HttpBaseDefine.h" 17 | 18 | 19 | using namespace NFrame; 20 | 21 | namespace NHttp 22 | { 23 | 24 | // 收到外部发送的GET消息协议,处理函数 25 | typedef bool (CHandler::*HttpGetOptHandler)(const char* connId, Connect* conn, const RequestHeader& reqHeaderData); 26 | struct HttpGetOptHandlerObject 27 | { 28 | CHandler* instance; 29 | HttpGetOptHandler handler; 30 | 31 | HttpGetOptHandlerObject() {}; 32 | HttpGetOptHandlerObject(CHandler* _instance, HttpGetOptHandler _handler) : instance(_instance), handler(_handler) {}; 33 | }; 34 | typedef unordered_map HttpGetOptHandlerInfo; // key 为用户注册时传递的URL 35 | 36 | // 收到外部发送的POST消息协议,处理函数 37 | typedef bool (CHandler::*HttpPostOptHandler)(const char* connId, Connect* conn, const RequestHeader& reqHeaderData, const HttpMsgBody& msgBody); 38 | struct HttpPostOptHandlerObject 39 | { 40 | CHandler* instance; 41 | HttpPostOptHandler handler; 42 | 43 | HttpPostOptHandlerObject() {}; 44 | HttpPostOptHandlerObject(CHandler* _instance, HttpPostOptHandler _handler) : instance(_instance), handler(_handler) {}; 45 | }; 46 | typedef unordered_map HttpPostOptHandlerInfo; // key 为用户注册时传递的URL 47 | 48 | // 内部发送http请求后收到外部的http应答消息,处理函数 49 | typedef bool (CHandler::*HttpReplyHandler)(ConnectData* cd); 50 | struct HttpReplyHandlerObject 51 | { 52 | CHandler* instance; 53 | HttpReplyHandler handler; 54 | 55 | HttpReplyHandlerObject() {}; 56 | HttpReplyHandlerObject(CHandler* _instance, HttpReplyHandler _handler) : instance(_instance), handler(_handler) {}; 57 | }; 58 | typedef unordered_map HttpReplyHandlerInfo; // key 为用户注册&发起请求时传递的requestId 59 | 60 | 61 | // http消息协议处理对象 62 | class CHttpDataHandler : public NFrame::CNetDataHandler 63 | { 64 | public: 65 | CHttpDataHandler(); 66 | ~CHttpDataHandler(); 67 | 68 | public: 69 | // 根据host获取ip&port 70 | bool getHostInfo(const char* host, strIP_t ip, unsigned short& port, const char* service = "http"); 71 | 72 | // 建立http连接,同时发送http请求数据 73 | bool doHttpConnect(const char* ip, unsigned int port, const char* host, const char* url, const CHttpRequest& httpRequest, 74 | const unsigned int requestId = 0, const char* userData = NULL, const unsigned int srcSrvId = 0, 75 | const UserCbData* cbData = NULL, const unsigned int cbDataLen = 0, const unsigned short protocolId = 0); 76 | 77 | // 建立http连接,同时发送http请求数据 78 | bool doHttpConnect(const char* ip, const unsigned short port, ConnectData* connData); 79 | 80 | public: 81 | // 获取&释放数据缓冲区 82 | char* getDataBuffer(unsigned int& len); 83 | void putDataBuffer(const char* dataBuff); 84 | 85 | public: 86 | // 注册http GET消息处理函数 87 | void registerGetOptHandler(const string& url, HttpGetOptHandler handler, CHandler* instance); 88 | 89 | // 注册http POST消息处理函数 90 | void registerPostOptHandler(const string& url, HttpPostOptHandler handler, CHandler* instance); 91 | 92 | // 注册http应答消息处理函数 93 | void registerHttpReplyHandler(unsigned int requestId, HttpReplyHandler handler, CHandler* instance); 94 | 95 | // 清理删除注册消息处理函数 96 | void clearGetOptHandler(); 97 | void clearPostOptHandler(); 98 | void clearHttpReplyHandler(); 99 | 100 | private: 101 | int onHandle(); // 主动发送的http请求收到应答消息 102 | 103 | void onClosedConnect(void* userData); // 连接关闭 104 | 105 | ConnectData* getConnectData(); 106 | void putConnectData(ConnectData* connData); 107 | 108 | private: 109 | // 被动收到外部的http请求消息 110 | virtual int onClientData(Connect* conn, const char* data, const unsigned int len); 111 | int handleRequest(Connect* conn, HttpRequestBuffer* ud); 112 | 113 | private: 114 | void onLoad(const char* srvName, const unsigned int srvId, unsigned short moduleId); 115 | void onUnLoad(const char* srvName, const unsigned int srvId, unsigned short moduleId); 116 | 117 | private: 118 | // 服务启动时被调用 119 | virtual int onInit(const char* srvName, const unsigned int srvId, unsigned short moduleId); 120 | 121 | // 服务停止时被调用 122 | virtual void onUnInit(const char* srvName, const unsigned int srvId, unsigned short moduleId); 123 | 124 | // 服务配置更新时被调用 125 | virtual void onUpdateConfig(); 126 | 127 | private: 128 | NCommon::CMemManager m_memForRequestBuffer; 129 | NCommon::CMemManager m_memForConnectData; 130 | CHttpConnectMgr m_httpConnectMgr; 131 | 132 | private: 133 | HttpGetOptHandlerInfo m_httpGetOptHandlerInfo; 134 | HttpPostOptHandlerInfo m_httpPostOptHandlerInfo; 135 | 136 | HttpReplyHandlerInfo m_httpReplyHandlerInfo; 137 | 138 | 139 | friend class CHttpSrv; 140 | 141 | DISABLE_COPY_ASSIGN(CHttpDataHandler); 142 | }; 143 | 144 | 145 | // Http 服务 146 | class CHttpSrv : public NFrame::IService 147 | { 148 | public: 149 | CHttpSrv(unsigned int srvType); 150 | ~CHttpSrv(); 151 | 152 | public: 153 | // 注册本服务的Http消息处理实例对象 154 | // 在回调函数onRegister中调用 155 | int registerHttpHandler(CHttpDataHandler* pInstance); 156 | 157 | public: 158 | virtual int onInit(const char* name, const unsigned int id); // 服务启动时被调用 159 | virtual void onUnInit(const char* name, const unsigned int id); // 服务停止时被调用 160 | virtual void onUpdateConfig(const char* name, const unsigned int id); // 服务配置更新时被调用 161 | 162 | virtual void onRegister(const char* name, const unsigned int id) = 0; // 服务启动后被调用,服务需在此注册本服务的各模块信息 163 | 164 | private: 165 | virtual int onHandle(); // 通知逻辑层处理逻辑 166 | 167 | virtual void onClosedConnect(void* userData); // 通知逻辑层对应的逻辑连接已被关闭 168 | 169 | 170 | private: 171 | CHttpDataHandler* m_httpDataHandler; 172 | 173 | 174 | DISABLE_COPY_ASSIGN(CHttpSrv); 175 | }; 176 | 177 | } 178 | 179 | #endif // CHTTP_SRV_H 180 | -------------------------------------------------------------------------------- /http_base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.6) 2 | 3 | SET(PROJECT_NAME httpbase) 4 | project(${PROJECT_NAME}) 5 | 6 | #包含公共头文件 7 | include(../../cmake/common.cmake) 8 | 9 | #包含当前目录所有源文件 10 | AUX_SOURCE_DIRECTORY(protocol PROTO_SOURCES) 11 | AUX_SOURCE_DIRECTORY(. CUR_SOURCES) 12 | SET(ALL_SOURCES ${CUR_SOURCES} ${PROTO_SOURCES}) 13 | 14 | #Generate the static library from the library sources 15 | add_library(${PROJECT_NAME} STATIC ${ALL_SOURCES}) -------------------------------------------------------------------------------- /http_base/HttpBaseDefine.h: -------------------------------------------------------------------------------- 1 | 2 | /* author : admin 3 | * date : 2015.04.23 4 | * description : 类型定义 5 | */ 6 | 7 | #ifndef __HTTP_BASE_DEFINE_H__ 8 | #define __HTTP_BASE_DEFINE_H__ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include "base/Type.h" 16 | 17 | 18 | using namespace std; 19 | 20 | namespace NHttp 21 | { 22 | 23 | // 常量定义 24 | static const unsigned int MaxReceiveNetBuffSize = 10240; 25 | static const unsigned int MaxNetBuffSize = 8192; 26 | static const unsigned int MaxDataQueueSize = 8192; 27 | static const unsigned int MaxRequestDataLen = 8192; 28 | static const unsigned int MaxRequestBufferCount = 32; 29 | static const unsigned int MaxConnectDataCount = 32; 30 | static const unsigned int MaxKeySize = 36; 31 | static const unsigned int MaxConnectIdLen = 36; 32 | 33 | // http 请求消息头部结束标识 34 | static const char* RequestHeaderFlag = "\r\n\r\n"; 35 | static const unsigned int RequestHeaderFlagLen = strlen(RequestHeaderFlag); 36 | 37 | static const unsigned short HttpsPort = 443; 38 | static const unsigned int HttpConnectTimeOut = 10; // 连接超时时间,单位秒 39 | 40 | // GET & POST 协议标识 41 | static const char* ProtocolGetMethod = "GET"; 42 | static const unsigned int ProtocolGetMethodLen = strlen(ProtocolGetMethod); 43 | static const char* ProtocolPostMethod = "POST"; 44 | static const unsigned int ProtocolPostMethodLen = strlen(ProtocolPostMethod); 45 | 46 | 47 | typedef unordered_map ParamKey2Value; 48 | 49 | // http 请求头部数据 50 | struct RequestHeader 51 | { 52 | const char* method; 53 | unsigned int methodLen; 54 | 55 | const char* url; 56 | unsigned int urlLen; 57 | 58 | ParamKey2Value paramKey2Value; 59 | }; 60 | 61 | // http 消息体数据 62 | struct HttpMsgBody 63 | { 64 | unsigned int len; 65 | 66 | ParamKey2Value paramKey2Value; 67 | }; 68 | 69 | // 收到外部的http请求数据 70 | // 该结构内存块也同时用作数据缓冲区使用(调用API接口get&put) 71 | struct HttpRequestBuffer 72 | { 73 | unsigned int reqDataLen; 74 | char reqData[MaxRequestDataLen]; // 收到的请求数据 75 | 76 | unsigned int connIdLen; 77 | char connId[MaxConnectIdLen]; // 连接ID标识 78 | }; 79 | 80 | // 连接服务状态 81 | enum SrvStatus 82 | { 83 | Stop = 0, 84 | Run = 1, 85 | Stopping = 2, 86 | }; 87 | 88 | // 连接状态 89 | enum ConnectStatus 90 | { 91 | Normal = 0, 92 | Connecting = 1, 93 | TimeOut = 2, 94 | AlreadyWrite = 3, 95 | CanRead = 4, 96 | ConnectError = 5, 97 | 98 | SSLConnecting = 6, 99 | SSLConnectError = 7, 100 | 101 | DataError = 8, 102 | }; 103 | 104 | // 连接上挂接的用户数据 105 | struct UserKeyData 106 | { 107 | unsigned int requestId; // 主动发送http请求对应的ID 108 | char key[MaxKeySize]; 109 | unsigned int srvId; 110 | unsigned short protocolId; 111 | }; 112 | 113 | // 用户挂接的回调数据 114 | struct UserCbData 115 | { 116 | unsigned int flag; // 0:默认内部管理内存; 1:外部挂接的内存由外部管理(创建&释放) 117 | }; 118 | 119 | // http连接对应的数据 120 | struct ConnectData 121 | { 122 | // 用户挂接和连接相关的数据 123 | UserKeyData keyData; 124 | 125 | // 需要发送的数据 126 | char sendData[MaxNetBuffSize]; 127 | unsigned int sendDataLen; 128 | unsigned int timeOutSecs; 129 | 130 | // 收到的数据 131 | char receiveData[MaxReceiveNetBuffSize]; 132 | unsigned int receiveDataLen; 133 | unsigned int receiveDataIdx; 134 | 135 | int fd; 136 | unsigned int lastTimeSecs; 137 | int status; // 连接状态 138 | 139 | SSL* sslConnect; // https 连接操作对象 140 | 141 | const UserCbData* cbData; // 用户挂接的数据 142 | }; 143 | 144 | } 145 | 146 | #endif // __HTTP_BASE_DEFINE_H__ 147 | 148 | --------------------------------------------------------------------------------