// 收到网络客户端的消息 int CGameModule::onClientMessage(const char* msgData, const unsigned int msgLen, const unsigned int msgId, unsigned int serviceId, unsigned short moduleId, unsigned short protocolId, Connect* conn) { if (protocolId >= MaxProtocolIDCount) { ReleaseErrorLog("receive net client msg error, protocolId = %d", protocolId); return InvalidParam; } ProtocolIdToHandler::const_iterator handlerIt = m_clientProtocolHanders->find(protocolId); if (handlerIt == m_clientProtocolHanders->end() || handlerIt->second.handler == NULL) { ReleaseErrorLog("not find the protocol handler for net client msg, protocolId = %d", protocolId); return NoFoundProtocolHandler; } // 填写消息上下文信息 m_netClientContext.serviceId = serviceId; m_netClientContext.moduleId = moduleId; m_netClientContext.protocolId = protocolId; m_netClientContext.msgId = msgId; m_netClientContext.conn = conn; // 业务逻辑处理消息 m_msgType = MessageType::NetClientMsg; (handlerIt->second.instance->*(handlerIt->second.handler))(msgData, msgLen, serviceId, moduleId, protocolId); m_netClientContext.protocolId = (unsigned short)-1; m_netClientContext.msgId = (unsigned int)-1; m_netClientContext.conn = NULL; return Success; }
void CSrvMsgHandler::onLoad(const char* srvName, const unsigned int srvId, unsigned short moduleId) { if (!GatewayProxyConfig::config::getConfigValue(CCfg::getValue("GatewayProxyService", "BusinessXmlConfigFile")).isSetConfigValueSuccess()) { ReleaseErrorLog("set business xml config value error"); stopService(); return; } const DBConfig::config& dbCfg = DBConfig::config::getConfigValue(CCfg::getValue("GatewayProxyService", "DbConfigFile")); if (!dbCfg.isSetConfigValueSuccess()) { ReleaseErrorLog("set db xml config value error"); stopService(); return; } if (!m_redisDbOpt.connectSvr(dbCfg.redis_db_cfg.center_db_ip.c_str(), dbCfg.redis_db_cfg.center_db_port, dbCfg.redis_db_cfg.center_db_timeout * MillisecondUnit)) { ReleaseErrorLog("gateway connect center redis service failed, ip = %s, port = %u, time out = %u", dbCfg.redis_db_cfg.center_db_ip.c_str(), dbCfg.redis_db_cfg.center_db_port, dbCfg.redis_db_cfg.center_db_timeout); stopService(); return; } static const unsigned int gatewayProxySrvId = getSrvId(); m_gatewayProxySrvData.ip = CSocket::toIPInt(CCfg::getValue("NetConnect", "NetIP")); // 外网IP m_gatewayProxySrvData.port = atoi(CCfg::getValue("NetConnect", "Port")); m_gatewayProxySrvData.curTimeSecs = time(NULL); m_gatewayProxySrvData.currentPersons = 0; int rc = m_redisDbOpt.setHField(GatewayProxyListKey, GatewayProxyListKeyLen, (const char*)&gatewayProxySrvId, sizeof(gatewayProxySrvId), (const char*)&m_gatewayProxySrvData, sizeof(m_gatewayProxySrvData)); if (rc != 0) { ReleaseErrorLog("set gateway proxy service data to redis center service failed, rc = %d", rc); stopService(); return; } m_gameHallId = GatewayProxyConfig::config::getConfigValue().commonCfg.game_hall_id; // 定时保存数据到redis unsigned int millisecondUnit = 1000; // 秒转换为毫秒乘值 unsigned int timerId = setTimer(millisecondUnit * atoi(CCfg::getValue("GatewayProxyService", "SaveDataToDBInterval")), (TimerHandler)&CSrvMsgHandler::saveDataToDb, 0, NULL, (unsigned int)-1); ReleaseInfoLog("gateway message handler load, service name = %s, id = %d, timer id = %u", srvName, srvId, timerId); }
int CLogicHandler::sendMsgToProxy(const char* msgData, const unsigned int msgLen, unsigned short protocolId, ConnectProxy* conn, unsigned int serviceId, unsigned short moduleId, unsigned int msgId) { int rc = m_service->sendMsgToProxy(msgData, msgLen, msgId, serviceId, moduleId, protocolId, conn); if (rc != Success) ReleaseErrorLog("send proxy message error3, msgLen = %u, serviceId = %d, moduleId = %d, protocolId = %d, rc = %d", msgLen, serviceId, moduleId, protocolId, rc); return rc; }
int CGameModule::sendMsgToClient(const char* msgData, const unsigned int msgLen, unsigned short protocolId, Connect* conn, unsigned int serviceId, unsigned short moduleId, unsigned int msgId) { int rc = m_service->sendMsgToClient(msgData, msgLen, msgId, serviceId, moduleId, protocolId, conn); if (rc != Success) ReleaseErrorLog("send client message error3, msgLen = %u, serviceId = %d, moduleId = %d, protocolId = %d, rc = %d", msgLen, serviceId, moduleId, protocolId, rc); return rc; }
// 向目标服务发送请求消息,默认自动发送上下文中存在的用户数据 // srcServiceProtocolId : 应答消息的处理协议ID,如果该消息存在应答的话 int CModule::sendMessage(const char* msgData, const unsigned int msgLen, unsigned short srcServiceType, unsigned int srcServiceId, unsigned short srcServiceProtocolId, unsigned int dstServiceId, unsigned short dstProtocolId, unsigned short dstModuleId, unsigned int msgId) { int rc = m_service->sendMessage(srcServiceType, srcServiceId, msgData, msgLen, m_context.userData, m_context.userDataLen, m_context.srvAsyncDataFlag, m_context.srvAsyncDataFlagLen, dstServiceId, dstProtocolId, dstModuleId, 0, srcServiceProtocolId, m_context.userFlag, msgId); if (rc != Success) ReleaseErrorLog("send service message error4, msgLen = %u, dstServiceId = %d, dstProtocolId = %d, rc = %d", msgLen, dstServiceId, dstProtocolId, rc); return rc; }
bool CDataHandler::readPkgHeader(Connect* curConn, unsigned int& dataSize) { char netPkgHeader[netPkgHeaderLen] = {0}; if (dataSize < netPkgHeaderLen) return false; if (readData(curConn, netPkgHeader, netPkgHeaderLen) != netPkgHeaderLen) { curConn->logicStatus = exception; // 逻辑数据异常了 ReleaseErrorLog("read net pkg header error, id = %lld, fd = %d, pkg header size = %d, data size = %d", curConn->id, curConn->fd, netPkgHeaderLen, dataSize); return false; } dataSize -= netPkgHeaderLen; // 剩余数据量 NetPkgHeader* pkgHeader = (NetPkgHeader*)netPkgHeader; if (pkgHeader->type == MSG) // 用户数据包 { pkgHeader->len = ntohl(pkgHeader->len); // 注意长度需要转成主机字节序 if (pkgHeader->len <= netPkgHeaderLen) { curConn->logicStatus = exception; // 逻辑数据异常了 ReleaseErrorLog("read user net pkg header error, id = %lld, fd = %d, pkg len = %d", curConn->id, curConn->fd, pkgHeader->len); return false; } curConn->needReadSize = pkgHeader->len - netPkgHeaderLen; // 用户数据包长度 return true; } else if (pkgHeader->type == CTL) // 控制类型数据包 { if (pkgHeader->cmd == HB_RP || pkgHeader->cmd == HB_RQ) // 心跳应答消息,心跳请求包 { curConn->heartBeatSecs = time(NULL); curConn->hbResult = 0; // 连接正常 static const NetPkgHeader hbReplyPkgHeader(htonl(netPkgHeaderLen), CTL, HB_RP); if (pkgHeader->cmd == HB_RQ) writeData(curConn, (const char*)&hbReplyPkgHeader, netPkgHeaderLen); // 发送心跳应答消息包 return (dataSize >= netPkgHeaderLen) ? readPkgHeader(curConn, dataSize) : false; // 继续尝试读取数据包头部 } } curConn->logicStatus = exception; // 逻辑数据异常了 ReleaseErrorLog("read net pkg header error, id = %lld, fd = %d, pkg len = %d, type = %d, cmd = %d", curConn->id, curConn->fd, pkgHeader->len, pkgHeader->type, pkgHeader->cmd); return false; }
int CLogicHandler::sendMsgToProxy(const char* msgData, const unsigned int msgLen, unsigned short protocolId, const char* userName, unsigned int serviceId, unsigned short moduleId, unsigned int msgId) { int rc = (userName != NULL) ? m_service->sendMsgToProxy(msgData, msgLen, msgId, serviceId, moduleId, protocolId, getConnectProxy(userName)) : InvalidParam; if (rc != Success) ReleaseErrorLog("send proxy message error2, msgLen = %u, serviceId = %d, moduleId = %d, protocolId = %d, rc = %d, userName = %s", msgLen, serviceId, moduleId, protocolId, rc, (userName != NULL) ? userName : ""); return rc; }
bool CDataHandler::readPkgBody(Connect* curConn, unsigned int dataSize, unsigned int& pkgLen, char* pkgData) { if (curConn->needReadSize > 0 && dataSize >= (unsigned int)curConn->needReadSize) { m_connMgr->setConnectNormal(curConn); // 有数据则填写活跃时间点 // 直接拷贝数据到缓冲区空间 if (pkgData != NULL) { if ((unsigned int)curConn->needReadSize > pkgLen) { ReleaseErrorLog("read net pkg failed, need read size = %d, pkg buff size = %d", curConn->needReadSize, pkgLen); return false; } if (readData(curConn, pkgData, curConn->needReadSize) == (unsigned int)curConn->needReadSize) // 从连接读出数据写入逻辑层buff { pkgLen = curConn->needReadSize; curConn->needReadSize = 0; // 下一次读取数据包头部 return true; } curConn->logicStatus = exception; // 逻辑数据异常了 ReleaseErrorLog("read net pkg data to buff error, id = %ld, fd = %d, need read size = %d, data size = %d", curConn->id, curConn->fd, curConn->needReadSize, dataSize); return false; } // 从逻辑层申请空间写数据 BufferHeader* buffHeader = m_logicHandler->getBufferHeader(); if (buffHeader != NULL) { if (readData(curConn, buffHeader->header, buffHeader->len) != buffHeader->len) // 先读头部数据 { curConn->logicStatus = exception; // 逻辑数据异常了 ReleaseErrorLog("read net pkg user header error, id = %ld, fd = %d, need read size = %d, data size = %d", curConn->id, curConn->fd, buffHeader->len, dataSize); return false; } curConn->needReadSize -= buffHeader->len; } void* logicCb = NULL; char* logicWriteBuff = m_logicHandler->getWriteBuffer(curConn->needReadSize, curConn->id, buffHeader, logicCb); if (curConn->needReadSize == 0) return true; // 存在只有用户数据包头的情况 if (logicWriteBuff != NULL) { bool isRead = (logicWriteBuff != (char*)-1); // 是否直接丢弃数据,false则丢弃数据 if (readData(curConn, logicWriteBuff, curConn->needReadSize, isRead) == (unsigned int)curConn->needReadSize) // 从连接读出数据写入逻辑层buff { if (isRead) m_logicHandler->submitWriteBuffer(logicWriteBuff, curConn->needReadSize, curConn->id, logicCb); // 提交数据到逻辑层 curConn->needReadSize = 0; // 下一次读取数据包头部 return true; } curConn->logicStatus = exception; // 逻辑数据异常了 ReleaseErrorLog("read net pkg body error, id = %ld, fd = %d, need read size = %d, data size = %d", curConn->id, curConn->fd, curConn->needReadSize, dataSize); } } return false; }
// 把data数据写入网络连接 bool CDataHandler::write(CConnectManager* connMgr, Connect* conn, const char* data, int len) { int wtLen = 0; if (getCanWriteDataSize(conn) == 0) { // 先直接写到socket缓冲区 if (!writeToSkt(connMgr, conn, data, len, wtLen)) return false; if (len == wtLen) return true; // 剩余未写完的数据写往临时缓冲区 data += wtLen; len -= wtLen; } CSingleW_SingleR_Buffer* writeBuff = conn->writeBuff; if (writeBuff == NULL) { // 第一次创建新内存块并挂接到链表上 writeBuff = connMgr->getWriteBuffer(); if (writeBuff == NULL) { ReleaseErrorLog("first time get no memory for write logic data to connect, id = %lld, fd = %d", conn->id, conn->fd); return false; // 好吧,内存没了这种不可思议的事情居然出现了,估计哪里有内存泄露了,太疯狂了。。。 } writeBuff->next = writeBuff; // 整成环型链表读写循环 conn->writeBuff = writeBuff; conn->curWriteIdx = writeBuff; } wtLen = writeBuff->write(data, len); if (wtLen < len) { // 下一块buff必须为空才能往里写数据,否则会导致读线程读的数据不连续而出现错误 CSingleW_SingleR_Buffer* next = writeBuff->next; if (next != writeBuff && next->isEmpty()) { char* readFlag = (char*)next; if (*(--readFlag) == 0) // 非当前正在读的buff才能执行写操作 { conn->writeBuff = next; // 条件满足则切换到下一块内存 return write(connMgr, conn, data + wtLen, len - wtLen); } } // 创建新内存块并挂接到链表上 CSingleW_SingleR_Buffer* newBuff = connMgr->getWriteBuffer(); if (newBuff == NULL) { ReleaseErrorLog("no memory for write logic new data to connect, id = %lld, fd = %d", conn->id, conn->fd); return false; // 好吧,内存没了这种不可思议的事情居然出现了,估计哪里有内存泄露了,太疯狂了。。。 } newBuff->next = next; writeBuff->next = newBuff; conn->writeBuff = newBuff; // 切换到下一块内存 return write(connMgr, conn, data + wtLen, len - wtLen); } return true; }
// 服务模块收到消息 int CModule::onServiceMessage(const char* msgData, const unsigned int msgLen, const char* userData, const unsigned int userDataLen, unsigned short dstProtocolId, unsigned int srcSrvId, unsigned short srcSrvType, unsigned short srcModuleId, unsigned short srcProtocolId, int userFlag, unsigned int msgId, const char* srvAsyncDataFlag, unsigned int srvAsyncDataFlagLen) { // if (dstProtocolId >= MaxProtocolIDCount || srcSrvType >= MaxServiceType || userDataLen > MaxUserDataLen || srcProtocolId >= MaxProtocolIDCount) if (srcSrvType >= MaxServiceType || userDataLen > MaxUserDataLen) { ReleaseErrorLog("receive msg error, srcServiceId = %d, srcServiceType = %d, dstProtocolId = %d, userDataLen = %d, srcProtocolId = %d", srcSrvId, srcSrvType, dstProtocolId, userDataLen, srcProtocolId); return InvalidParam; } CHandler* instance = NULL; ProtocolHandler handler = NULL; if (dstProtocolId < MaxProtocolIDCount) { MsgHandler& msgHandler = m_protocolHanders[srcSrvType][dstProtocolId]; if (msgHandler.handler == NULL) msgHandler = m_protocolHanders[CommonSrv][dstProtocolId]; // 默认取公共协议 if (msgHandler.handler != NULL) { instance = msgHandler.instance; handler = msgHandler.handler; } } else { ProtocolIdToHandler::const_iterator handlerIt = m_serviceProtocolHandler.find(dstProtocolId); if (handlerIt != m_serviceProtocolHandler.end() && handlerIt->second.handler != NULL) { instance = handlerIt->second.instance; handler = handlerIt->second.handler; } } if (instance == NULL) { ReleaseErrorLog("can not find the protocol handler, srcServiceId = %d, srcServiceType = %d, dstProtocolId = %d", srcSrvId, srcSrvType, dstProtocolId); return NoFoundProtocolHandler; } // 填写消息上下文信息 m_context.srcSrvId = srcSrvId; m_context.srcSrvType = srcSrvType; m_context.srcModuleId = srcModuleId; m_context.srcProtocolId = srcProtocolId; m_context.dstProtocolId = dstProtocolId; if (userDataLen > 0) memcpy(m_context.userData, userData, userDataLen); m_context.userData[userDataLen] = '\0'; m_context.userDataLen = userDataLen; m_context.userFlag = userFlag; // 异步数据标识 if (srvAsyncDataFlagLen > 0) memcpy(m_context.srvAsyncDataFlag, srvAsyncDataFlag, srvAsyncDataFlagLen); m_context.srvAsyncDataFlag[srvAsyncDataFlagLen] = '\0'; m_context.srvAsyncDataFlagLen = srvAsyncDataFlagLen; // 业务逻辑处理消息 m_msgType = MessageType::InnerServiceMsg; (instance->*handler)(msgData, msgLen, srcSrvId, srcModuleId, srcProtocolId); m_context.dstProtocolId = (unsigned short)-1; m_context.userData[0] = '\0'; m_context.userDataLen = 0; m_context.userFlag = 0; m_context.srvAsyncDataFlag[0] = '\0'; m_context.srvAsyncDataFlagLen = 0; return Success; }