/** * @file gatesrv.cpp * @brief gatesrv主文件 * Copyright(c) 2007,上海第九城市游戏研发部 * All rights reserved * 文件名称:gatesrv.cpp * 摘 要:gatesrv主程序 * 作 者:dzj * 完成日期:2007.11.20 */ #include "../../Base/aceall.h" #include "../../Base/BufQueue/BufQueueImp.h" #include "../../Base/PkgProc/RcvPkgHandler.h" //收包处理器(CRcvPkgHandler); #include "../../Base/PkgProc/CManCommHandler.h" //所有连接管理器; #include "../../Base/LoadConfig/LoadSrvConfig.h" //读服务配置; #include "../../Base/NetTaskEx.h"//网络模块需要; #include "../../Base/HandlerUdp.h" #include "Player/Player.h" //给客户端收包处理器提供包处理者; #include "OtherServer/otherserver.h" //给其它srv收包处理器提供包处理者; #include "mapteleport/MapTeleporterManager.h" #include "toolmonitor/toolmonitor.h" #include "../../Test/testthreadque_wait/sigexception/sigexception.h" #ifdef ACE_WIN32 #pragma warning( push ) #pragma warning( disable: 4819 ) //"type cast" pointer truncation from ??* to ?? #endif //ACE_WIN32 #include "../../Base/PkgProc/AssignProtocol.h"//assignsrv相关协议 # include "../../Base/PkgProc/MonitorProtocol.h"//监控相关协议 #ifdef ACE_WIN32 #pragma warning( pop ) #endif //ACE_WIN32 #ifdef ANTI_ADDICTION #include "AddictionPlayerList.h" #endif //ANTI_ADDICTION //crash模块 #ifdef ACE_WIN32 #include "CrashLib/CrashLib.h" #endif #ifdef USE_DSIOCP #include "iocp/dsiocp.h" #endif //USE_DSIOCP #ifdef DS_EPOLL #include #include #include "../../Test/testthreadque_wait/threadrwque.h" #include "../../Test/testthreadque_wait/buflog.h" #include #include "../../Test/testthreadque_wait/lsocket.h" #include "../../Test/testthreadque_wait/apppoolobjs.h" #include "../../Test/testthreadque_wait/manframe/manframe.h" bool g_IsSrv = true;//服务端; #endif //DS_EPOLL #ifdef ACE_WIN32 //查找windows下的异常中断信号 #include typedef void (*SignalHandlerPointer)(int); SignalHandlerPointer g_pfnPreABRTHandler = NULL; SignalHandlerPointer g_pfnPreFPEHandler = NULL; SignalHandlerPointer g_pfnPreILLHandler = NULL; SignalHandlerPointer g_pfnPreINTHandler = NULL; SignalHandlerPointer g_pfnPreSEGVHandler = NULL; SignalHandlerPointer g_pfnPreTERMHandler = NULL; #endif //ACE_WIN32 #ifdef USE_DSIOCP TCache< DsIOBuf >* g_poolDsIOBuf = NULL; TCache< CDsSocket >* g_poolDsSocket = NULL; TCache< UniqueObj< CDsSocket > >* g_poolUniDssocket = NULL; TCache< PerIOData >* g_poolPerIOData = NULL; #endif //USE_DSIOCP #ifndef DS_EPOLL ///向客户端发包的队列; IBufQueue* g_pClientSender = NULL;//向客户端发包的队列; #endif //DS_EPOLL IBufQueue* g_pSrvSender = NULL; //向服务器其它srv发包的队列; TCache< MsgToPut >* g_poolMsgToPut = NULL; //全局消息对象池 unsigned short SELF_SRV_ID = 0x00; //自身为第几个GateSrv; vector g_vecKickMapSrvPlayer; //是否因为mapsrv断线而踢去对应该mapsrv的所有玩家; ///连接LoginSrv; void ConnectLoginSrv( unsigned long loginsrvID ) { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetLoginSrvAddr(loginsrvID) ) { //如果没有loginsrv,则放弃连接; return; } if ( NULL != CManLoginSrvs::GetLoginserver(/*loginsrvID*/) ) { //如果已连接,则不再重连; return; } //以下连接loginsrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectLoginSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = LOGINSRV_SID_BASE;//暂时只设一个loginsrv,以后若需添加再修改 tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char loginsrvaddr[32]; StructMemSet( loginsrvaddr, 0, sizeof(loginsrvaddr) ); #ifdef ACE_WIN32 sprintf_s( loginsrvaddr, sizeof(loginsrvaddr), "%s:%d", CLoadSrvConfig::GetLoginSrvAddr(loginsrvID), CLoadSrvConfig::GetLoginSrvPort(loginsrvID) );//目前只有一个loginsrv; #else //ACE_WIN32 sprintf( loginsrvaddr, "%s:%d", CLoadSrvConfig::GetLoginSrvAddr(loginsrvID), CLoadSrvConfig::GetLoginSrvPort(loginsrvID) );//目前只有一个loginsrv; #endif //ACE_WIN32 SafeStrCpy( tmpMsg->pMsg, loginsrvaddr ); if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectLoginSrv, PushMsg失败\n" ); } else D_INFO("连接LoginSrv :%d的消息已经发出 loginsrvaddr:%s:%d\n", loginsrvID, CLoadSrvConfig::GetLoginSrvAddr(loginsrvID), CLoadSrvConfig::GetLoginSrvPort(loginsrvID)); return; TRY_END; return; } ///连接CenterSrv; void ConnectCenterSrv() { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetCenterSrvAddr() ) { //如果没有centersrv,则放弃连接; return; } if ( NULL != CManCenterSrvs::GetCenterserver() ) { //如果已连接,则不再重连; return; } //以下连接centersrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectCenterSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = CENTERSRV_SID_BASE; tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char centersrvaddr[32]; StructMemSet( centersrvaddr, 0, sizeof(centersrvaddr) ); #ifdef ACE_WIN32 sprintf_s( centersrvaddr, sizeof(centersrvaddr), "%s:%d", CLoadSrvConfig::GetCenterSrvAddr(), CLoadSrvConfig::GetCenterSrvPort() );//只有一个centersrv; #else //ACE_WIN32 sprintf( centersrvaddr, "%s:%d", CLoadSrvConfig::GetCenterSrvAddr(), CLoadSrvConfig::GetCenterSrvPort() );//只有一个centersrv; #endif //ACE_WIN32 SafeStrCpy( tmpMsg->pMsg, centersrvaddr ); if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectCenterSrv, PushMsg失败\n" ); } else D_INFO("连接CenterSrv :的消息已经发出 centersrvaddr:%s:%d\n", CLoadSrvConfig::GetCenterSrvAddr(), CLoadSrvConfig::GetCenterSrvPort()); return; TRY_END; return; } ///连接DbSrv; void ConnectDbSrv( unsigned short dbsrvID ) { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetDbSrvAddr(dbsrvID) ) { //如果没有dbsrv,则放弃连接; return; } if ( NULL != CManDbSrvs::GetDbsrvByID(dbsrvID) ) { //如果已连接,则不再重连; return; } //以下连接dbsrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectDbSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = DBSRV_SID_BASE+dbsrvID;//暂时只设一个dbsrv,以后若需添加再修改,改成多个dbsrv, by dzj, 09.01.19 tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char dbsrvaddr[32]; StructMemSet( dbsrvaddr, 0, sizeof(dbsrvaddr) ); #ifdef ACE_WIN32 sprintf_s( dbsrvaddr, sizeof(dbsrvaddr), "%s:%d", CLoadSrvConfig::GetDbSrvAddr(dbsrvID), CLoadSrvConfig::GetDbSrvPort(dbsrvID) );//只有一个dbsrv, 改成多个dbsrv, by dzj, 09.01.19; strcpy_s( tmpMsg->pMsg, sizeof(tmpMsg->pMsg), dbsrvaddr ); #else //ACE_WIN32 sprintf( dbsrvaddr, "%s:%d", CLoadSrvConfig::GetDbSrvAddr(dbsrvID), CLoadSrvConfig::GetDbSrvPort(dbsrvID) );//只有一个dbsrv, 改成多个dbsrv, by dzj, 09.01.19; strcpy( tmpMsg->pMsg, dbsrvaddr ); #endif //ACE_WIN32 if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectDbSrv, PushMsg失败\n" ); } D_INFO("连接DbSrv :%d的消息已经发出,SrvAddr:%s:%d\n",dbsrvID,CLoadSrvConfig::GetDbSrvAddr(dbsrvID),CLoadSrvConfig::GetDbSrvPort(dbsrvID) ); return; TRY_END; return; } ///连接RankSrv; void ConnectRankSrv( unsigned short ranksrvID ) { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetRandSrvAddr(ranksrvID) ) { //如果没有rankSrv地址,则放弃连接; return; } //以下连接ranksrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectDbSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = RANKSRV_SID_BASE + ranksrvID;//暂时只设一个ranksrv,以后若需添加再修改 tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char dbsrvaddr[32]; StructMemSet( dbsrvaddr, 0, sizeof(dbsrvaddr) ); #ifdef ACE_WIN32 sprintf_s( dbsrvaddr, sizeof(dbsrvaddr), "%s:%d", CLoadSrvConfig::GetRandSrvAddr(ranksrvID), CLoadSrvConfig::GetRandSrvPort(ranksrvID) );//只有一个ranksrv, 改成多个ranksrv strcpy_s( tmpMsg->pMsg, sizeof(tmpMsg->pMsg), dbsrvaddr ); #else //ACE_WIN32 sprintf( dbsrvaddr, "%s:%d", CLoadSrvConfig::GetRandSrvAddr(ranksrvID), CLoadSrvConfig::GetRandSrvPort(ranksrvID) );//只有一个rank, 改成多个ranksrv strcpy( tmpMsg->pMsg, dbsrvaddr ); #endif //ACE_WIN32 if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectRankSrv, PushMsg失败\n" ); } else D_INFO("连接RankSrv :%d的消息已经发出 RandSrvAddr:%s:%d\n",ranksrvID, CLoadSrvConfig::GetRandSrvAddr(ranksrvID), CLoadSrvConfig::GetRandSrvPort(ranksrvID) ); TRY_END; return; } ///连接NewLoginSrv; void ConnectNewLoginSrv() { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetNewLoginSrvAddr() ) { //如果没有relationsrv,则放弃连接; return; } if ( NULL != CManNewLoginSrv::GetNewLoginSrv() ) { //如果已连接,则不再重连; return; } //以下连接dbsrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectNewLoginSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = NEWLOGINSRV_SID_BASE;//暂时只设一个relationsrv,以后若需添加再修改 tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char newloginsrvaddr[32]; StructMemSet( newloginsrvaddr, 0, sizeof(newloginsrvaddr) ); #ifdef ACE_WIN32 sprintf_s( newloginsrvaddr, sizeof(newloginsrvaddr), "%s:%d", CLoadSrvConfig::GetNewLoginSrvAddr(), CLoadSrvConfig::GetNewLoginSrvPort() );//只有一个NewLoginSrv; strcpy_s( tmpMsg->pMsg, sizeof(tmpMsg->pMsg), newloginsrvaddr ); #else //ACE_WIN32 sprintf( newloginsrvaddr, "%s:%d", CLoadSrvConfig::GetNewLoginSrvAddr(), CLoadSrvConfig::GetNewLoginSrvPort() );//只有一个NewLoginSrv; strcpy( tmpMsg->pMsg, newloginsrvaddr ); #endif //ACE_WIN32 if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectNewLoginSrv, PushMsg失败\n" ); } else D_INFO("连接NewLoginSrv :的消息已经发出 loginsrvaddr:%s:%d\n", CLoadSrvConfig::GetNewLoginSrvAddr(), CLoadSrvConfig::GetNewLoginSrvPort()); return; TRY_END; return; } ///连接RelationSrv; void ConnectRelationSrv() { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetRelationSrvAddr() ) { //如果没有relationsrv,则放弃连接; return; } if ( NULL != CManRelationSrvs::GetRelationserver() ) { //如果已连接,则不再重连; return; } //以下连接dbsrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectRelationSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = RELATIONSRV_SID_BASE;//暂时只设一个relationsrv,以后若需添加再修改 tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char relationsrvaddr[32]; StructMemSet( relationsrvaddr, 0, sizeof(relationsrvaddr) ); #ifdef ACE_WIN32 sprintf_s( relationsrvaddr, sizeof(relationsrvaddr), "%s:%d", CLoadSrvConfig::GetRelationSrvAddr(), CLoadSrvConfig::GetRelationSrvPort() );//只有一个relationsrv; strcpy_s( tmpMsg->pMsg, sizeof(tmpMsg->pMsg), relationsrvaddr ); #else //ACE_WIN32 sprintf( relationsrvaddr, "%s:%d", CLoadSrvConfig::GetRelationSrvAddr(), CLoadSrvConfig::GetRelationSrvPort() );//只有一个relationsrv; strcpy( tmpMsg->pMsg, relationsrvaddr ); #endif //ACE_WIN32 if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectRelationSrv, PushMsg失败\n" ); } else D_INFO("连接relationsrv 的消息已经发出 relationsrvaddr:%s:%d\n", CLoadSrvConfig::GetRelationSrvAddr(), CLoadSrvConfig::GetRelationSrvPort()); return; TRY_END; return; } ///连接ShopSrv; void ConnectShopSrv() { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetShopSrvAddr() ) { //如果没有shoprv,则放弃连接; return; } if ( NULL != CManShopSrvs::GetShopserver() ) { //如果已连接,则不再重连; return; } //以下连接shopsrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectShopSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = SHOP_SID_BASE;//暂时只设一个shopsrv,以后若需添加再修改 tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char shopsrvaddr[32]; StructMemSet( shopsrvaddr, 0, sizeof(shopsrvaddr) ); #ifdef ACE_WIN32 sprintf_s( shopsrvaddr, sizeof(shopsrvaddr), "%s:%d", CLoadSrvConfig::GetShopSrvAddr(), CLoadSrvConfig::GetShopSrvPort() );//只有一个shopsrv; strcpy_s( tmpMsg->pMsg, sizeof(tmpMsg->pMsg), shopsrvaddr ); #else //ACE_WIN32 sprintf( shopsrvaddr, "%s:%d", CLoadSrvConfig::GetShopSrvAddr(), CLoadSrvConfig::GetShopSrvPort() );//只有一个shopsrv; strcpy( tmpMsg->pMsg, shopsrvaddr ); #endif //ACE_WIN32 if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectShopSrv, PushMsg失败\n" ); } else D_INFO("连接ShopSrv 的消息已经发出 shopsrvaddr:%s:%d\n", CLoadSrvConfig::GetShopSrvAddr(), CLoadSrvConfig::GetShopSrvPort()); return; TRY_END; return; } ///连接指定的MapSrv; void ConnectMapSrv( unsigned short mapsrvID /*欲连接mapsrv在所有mapsrv中的序号*/) { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetMapSrvAddr(mapsrvID) ) { //如果没有这个mapsrv,则放弃连接; return; } if ( NULL != CManMapSrvs::GetMapserver( mapsrvID ) ) { //如果已连接,则不再重连; return; } //以下连接mapsrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectMapSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = MAPSRV_SID_BASE + mapsrvID;//mapsrv0 tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char mapsrvaddr[32]; StructMemSet( mapsrvaddr, 0, sizeof(mapsrvaddr) ); #ifdef ACE_WIN32 sprintf_s( mapsrvaddr, sizeof(mapsrvaddr), "%s:%d", CLoadSrvConfig::GetMapSrvAddr(mapsrvID), CLoadSrvConfig::GetMapSrvPort(mapsrvID) );//第一个mapsrv; strcpy_s( tmpMsg->pMsg, sizeof(tmpMsg->pMsg), mapsrvaddr ); #else //ACE_WIN32 sprintf( mapsrvaddr, "%s:%d", CLoadSrvConfig::GetMapSrvAddr(mapsrvID), CLoadSrvConfig::GetMapSrvPort(mapsrvID) );//第一个mapsrv; strcpy( tmpMsg->pMsg, mapsrvaddr ); #endif //ACE_WIN32 if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectMapSrv, PushMsg失败\n" ); } else D_INFO("连接MapSrv :%d的消息已经发出 mapsrvaddr:%s:%d\n", mapsrvID,CLoadSrvConfig::GetMapSrvAddr(mapsrvID), CLoadSrvConfig::GetMapSrvPort(mapsrvID)); return; TRY_END; return; } ///连接LogSrv; void ConnectLogSrv() { TRY_BEGIN; if ( NULL == CLoadSrvConfig::GetLogSrvAddr() ) { //如果没有logsrv,则放弃连接; return; } if ( NULL != CManLogSrvs::GetLogserver() ) { //如果已连接,则不再重连; return; } //以下连接logsrv MsgToPut* tmpMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == tmpMsg ) { TRY_BEGIN; D_ERROR( "ConnectLogSrv时,g_poolMsgToPut,内存分配失败\n" ); TRY_END; return; } tmpMsg->nSessionID = LOG_SID_BASE;//暂时只设一个shopsrv,以后若需添加再修改 tmpMsg->nHandleID = 0; tmpMsg->nMsgLen = -1;//连接服务器; char logsrvaddr[32]; StructMemSet( logsrvaddr, 0, sizeof(logsrvaddr) ); #ifdef ACE_WIN32 sprintf_s( logsrvaddr, sizeof(logsrvaddr), "%s:%d", CLoadSrvConfig::GetLogSrvAddr(), CLoadSrvConfig::GetLogSrvPort() );//只有一个Logsrv; strcpy_s( tmpMsg->pMsg, sizeof(tmpMsg->pMsg), logsrvaddr ); #else //ACE_WIN32 sprintf( logsrvaddr, "%s:%d", CLoadSrvConfig::GetLogSrvAddr(), CLoadSrvConfig::GetLogSrvPort() );//只有一个Logsrv; strcpy( tmpMsg->pMsg, logsrvaddr ); #endif //ACE_WIN32 if ( g_pSrvSender->PushMsg( tmpMsg ) < 0 ) { D_ERROR( "0926dbg, ConnectLogSrv, PushMsg失败\n" ); } else D_INFO("连接LogSrv :的消息已经发出 logsrvaddr:%s:%d\n", CLoadSrvConfig::GetLogSrvAddr(), CLoadSrvConfig::GetLogSrvPort()); return; TRY_END; return; } //连接所有DbSrv; void ConnectAllDbSrv() { TRY_BEGIN; for ( unsigned short i=DBSRV_SID_BASE; iReleaseUdpHandle(); delete m_pAssignSrvHandle; m_pAssignSrvHandle = NULL; return true; } template bool AssignSrvSendPkg( T_Msg& msgToSend ) { if ( NULL == m_pAssignSrvHandle ) { return false; } if ( sizeof(msgToSend) + 5 >= sizeof( m_SendBuf ) ) { D_ERROR( "向assignsrv发送包%x,包大小越界\n", T_Msg::wCmd ); return false; } int iEncodeLen = 0; iEncodeLen = (int)m_assignPro.EnCode(int(T_Msg::wCmd), &msgToSend, m_SendBuf + 5, sizeof(m_SendBuf) - 5); if(iEncodeLen < -1) { D_ERROR( "向assignsrv发送包%x,组包失败\n", T_Msg::wCmd ); return false; } unsigned short wLen = iEncodeLen + 5; unsigned short wCmd = T_Msg::wCmd; unsigned char ucType = G_A; ACE_OS::memcpy(&m_SendBuf[0], &wLen, 2); ACE_OS::memcpy(&m_SendBuf[2], &ucType, 1); ACE_OS::memcpy(&m_SendBuf[3], &wCmd, 2); m_pAssignSrvHandle->Send( m_SendBuf, wLen ); return true; } private: CHandlerUdp* m_pAssignSrvHandle; static Assign_namespace::AssignProtocol m_assignPro; static char m_SendBuf[512]; }; Assign_namespace::AssignProtocol AssignSrvSend::m_assignPro; char AssignSrvSend::m_SendBuf[512]; AssignSrvSend g_AssignSrvSend; ///通知AssignSrv帐号与地图号对应信息; void AssignSrvReportAccountMap( const char* playerAccount, unsigned int mapid ) { if ( NULL == playerAccount ) { return; } Assign_namespace::GANotifyPlayerMapId msg; msg.accountLen = (USHORT) (strlen( playerAccount )); if ( msg.accountLen >= sizeof( msg.account ) ) { //帐号名超长; D_ERROR( "AssignSrvReportAccountMap,通知的帐号名超长\n" ); return; } SafeStrCpy( msg.account, playerAccount ); msg.mapId = mapid; g_AssignSrvSend.AssignSrvSendPkg( msg ); return; } ///通知AssignSrv本Gate负载信息; void AssignSrvReportLoad(void) { //static const char *pszAssignAddr = CLoadSrvConfig::GetAssignSrvAddr(); //static const unsigned short usAssignPort = CLoadSrvConfig::GetAssignSrvPort(); static const char *pszGateAddr = CLoadSrvConfig::GetOuterListenAddr(); static const unsigned short usGatePort = CLoadSrvConfig::GetOuterListenPort(); //static Assign_namespace::AssignProtocol assignPro; //static CHandlerUdp handler(pszAssignAddr, usAssignPort); Assign_namespace::GAGateSrvMsg msg; msg.IP = inet_addr(pszGateAddr); msg.Port = htons(usGatePort); msg.Num = CManPlayer::GetPlayerNum(); g_AssignSrvSend.AssignSrvSendPkg( msg ); //char szEncodeBuffer[sizeof(Assign_namespace::GAGateSrvMsg) + 5] = {0}; //int iEncodeLen = 0; //iEncodeLen = (int)assignPro.EnCode(int(Assign_namespace::GAGateSrvMsg::wCmd), &msg, szEncodeBuffer + 5, sizeof(szEncodeBuffer) - 5); //if(iEncodeLen < -1) // return; // //unsigned short wLen = iEncodeLen + 5; //unsigned short wCmd = Assign_namespace::GAGateSrvMsg::wCmd; //unsigned char ucType = G_A; //ACE_OS::memcpy(&szEncodeBuffer[0], &wLen, 2); //ACE_OS::memcpy(&szEncodeBuffer[2], &ucType, 1); //ACE_OS::memcpy(&szEncodeBuffer[3], &wCmd, 2); //handler.Send(szEncodeBuffer, wLen); return; } #ifdef USE_SIG_TRY bool ExceptionCheck() { if( g_isException ) { GESrvGroupChat expMsg; stringstream ss; ss <<"GateSrv ID:" << CLoadSrvConfig::GetSelfID() <<"发生异常"; SafeStrCpy( expMsg.chatContent, ss.str().c_str() ); expMsg.chatType = CT_WORLD_CHAT; expMsg.extInfo = CT_SYS_EVENT_NOTI; SendMsgToCenterSrv( GESrvGroupChat, expMsg ); } return true; } #endif //USE_SIG_TRY ///时钟检测函数,循环执行以确定是否需要执行快时钟或慢时钟; void TimerCheck() { TRY_BEGIN; static ACE_Time_Value fastLastTime = ACE_OS::gettimeofday(); static ACE_Time_Value slowLastTime = ACE_OS::gettimeofday(); ACE_Time_Value curTime = ACE_OS::gettimeofday(); ACE_Time_Value fastPastTime = curTime - fastLastTime; ACE_Time_Value slowPastTime = curTime - slowLastTime; if ( fastPastTime.msec() > 361 ) //36毫秒; { //激活快时钟; fastLastTime = curTime; #ifndef DS_EPOLL CManPlayer::ManPlayerFastTimer(); #endif //DS_EPOLL } if ( slowPastTime.msec() > 517 ) //517毫秒; { //激活慢时钟; slowLastTime = curTime; //发送负载信息到assignsrv AssignSrvReportLoad(); } #ifdef USE_SIG_TRY static ACE_Time_Value exceptionCheckLastTime = ACE_OS::gettimeofday(); ACE_Time_Value exceptionPastTime = curTime - exceptionCheckLastTime; if( exceptionPastTime.sec() >= 10 ) //每10秒检测一次 { exceptionCheckLastTime = curTime; ExceptionCheck(); } #endif //USE_SIG_TRY return; TRY_END; } #ifndef ACE_WIN32 void catchpipe(int signo) { signo = signo; D_WARNING( "收到SIGPIPE信号,忽略" ); } #endif //ACE_WIN32 static void sigIntHandler(int signo) { D_DEBUG("收到%d(sigint)信号", signo); return; } ///应用程序主函数; int ACE_TMAIN(int argc, ACE_TCHAR* argv[]) { TRY_BEGIN; MainInitTls(); #ifdef DS_EPOLL InitGloblePools(); #endif //DS_EPOLL srand( (unsigned int)time(0) ); //取随机种 //首先连监控服务器; if ( ! InitToolMonitor() ) { D_ERROR( "连接平台监控模块失败!\n" ); return 0; } if( Parse_args( argc, argv ) == -1 ) return 0; if ( g_iLogType <= 2 || g_iLogType >= 0 ) { SetLog("Debug_log.txt",g_iLogType ); } else { return 0; } #ifdef ACE_WIN32 CCrashLib CrashHandler; #endif SetTSTP();//TSTP信号终止程序添加 // 捕捉SIGINT信号 ACE_Sig_Action handleSigInt(reinterpret_cast (sigIntHandler), SIGINT); ACE_UNUSED_ARG(handleSigInt); // 忽略SIGPIPE信号 ACE_Sig_Action noSigPipe((ACE_SignalHandler)SIG_IGN/*(sigPipeHandler)*/, SIGPIPE); ACE_UNUSED_ARG(noSigPipe); #ifndef DS_EPOLL g_poolMsgToPut = NEW TCache< MsgToPut >( 100000 );//全局MsgToPut对象池; CManPlayer::InitManPlayer(); #else //DS_EPOLL DsEvent srvwriteEvent;//服务端写事件,客户端不使用bufqueue,不需要客户端写事件; DsEvent clisrvreadEvent;//客户端、服务端读事件; CManFrame* pTestManFrame = NEW CManFrame( clisrvreadEvent, 32000 ); //只用于SRV端的通信,因此池不需要原来那么大; g_poolMsgToPut = NEW TCache< MsgToPut >( 40000 );//全局MsgToPut对象池; CManPlayer::InitManPlayer( pTestManFrame ); #endif //DS_EPOLL #ifdef USE_DSIOCP CDsSocket::Init(); g_poolPerIOData = NEW TCache< PerIOData >( 50000 );//尽量分配足够; g_poolUniDssocket = NEW TCache< UniqueObj< CDsSocket > >( 50000 );//尽量分配足够; g_poolDsSocket = NEW TCache< CDsSocket>( 6000 );//全局DsSocket对象池,必须分配足够,因为只能使用Retrieve而不能使用RetrieveOrCreate; g_poolDsIOBuf = NEW TCache< DsIOBuf >( 24000 );//因为gatesrv连接数多 #endif //USE_DSIOCP //// 创建全局小缓冲块池 //g_poolSmallMB = NEW CCacheMessageBlock(10, 50*1024); //if(g_poolSmallMB == NULL) // return -1; //auto_ptr< CCacheMessageBlock > poolAutoCleanSmall(g_poolSmallMB); //读服务配置信息; if ( ! CLoadSrvConfig::LoadConfig() ) { D_WARNING( "服务配置错!服务启动失败\n" ); return 0; } SELF_SRV_ID = (unsigned short) CLoadSrvConfig::GetSelfID(); D_INFO( "服务类型GateSrv,序号:%d\n", CLoadSrvConfig::GetSelfID() ); if ( g_AssignSrvSend.InitAssignSrvSend() ) { D_INFO( "初始化assignsrv发包,成功\n" ); } else { D_ERROR( "初始化assignsrv发包,失败\n" ); return 0; } //初始化各收包处理函数; CDealPlayerPkg::Init(); CDealMapSrvPkg::Init(); CDealDbSrvPkg::Init(); CDealCenterSrvPkg::Init(); CDealLoginSrvPkg::Init(); CDealRelationSrvPkg::Init(); CDealNewLoginSrvPkg::Init(); CDealRankSrvPkg::Init(); CDealShopSrvPkg::Init(); CMapTeleManagerSingle::instance()->Init("config/mapconfig/mapteleporters.xml");//初始化地图跳转点; PkgStatManager::Init(); #ifdef DS_EPOLL IBufQueue* pSrvReadQueue = NEW CBufQueue(clisrvreadEvent);//与客户端共用一个读事件,从此队列读其它srv网络消息; IBufQueue* pSrvWriteQueue = NEW CBufQueue(srvwriteEvent);//向此队列写其它srv网络消息; #else //DS_EPOLL IBufQueue* pClientReadQueue = NEW CBufQueue;//从此队列读客户端网络消息; IBufQueue* pClientWriteQueue = NEW CBufQueue;//向此队列写客户端网络消息; g_pClientSender = pClientWriteQueue;//客户端发包器; IBufQueue* pSrvReadQueue = NEW CBufQueue();//从此队列读其它srv网络消息; IBufQueue* pSrvWriteQueue = NEW CBufQueue();//向此队列写其它srv网络消息; #endif //DS_EPOLL g_pSrvSender = pSrvWriteQueue;//其它srv发包器; #ifdef USE_DSIOCP CDsIocp< IBufQueue, IBufQueue, CDsSocket >* srvIocp = NEW CDsIocp< IBufQueue, IBufQueue, CDsSocket >; srvIocp->Init( 128, pSrvReadQueue, pSrvWriteQueue ); //need not listen srv_in_connection, by dzj, 08.08.18,srvIocp->AddListen( CLoadSrvConfig::GetListenPort() ); CDsIocp< IBufQueue, IBufQueue, CDsSocket >* cliIocp = NEW CDsIocp< IBufQueue, IBufQueue, CDsSocket >; cliIocp->Init( 5000, pClientReadQueue, pClientWriteQueue ); D_INFO( "监听地址:%s:%d...\n", CLoadSrvConfig::GetOuterListenAddr(), CLoadSrvConfig::GetOuterListenPort() ); if ( ! (cliIocp->AddListenByAddr( CLoadSrvConfig::GetOuterListenAddr(), CLoadSrvConfig::GetOuterListenPort() )) ) { D_ERROR( "监听地址失败\n" ); return 0; } D_INFO( "监听成功\n" ); //cliIocp->AddListen( CLoadSrvConfig::GetOuterListenPort() ); #else //US_DSIOCP #ifdef DS_EPOLL NewLog( LOG_LEV_ERROR, "测试dsepoll..." ); CDsEPoll* pEPoll = NEW CDsEPoll[3]; CLSocket* listenSock = NEW CLSocket(); if ( !(listenSock->AddSelfToFrame(pTestManFrame) ) ) { delete listenSock; listenSock = NULL; return 0; } listenSock->SetEPollArr( pEPoll, 3 ); listenSock->LSListen( CLoadSrvConfig::GetOuterListenAddr(), CLoadSrvConfig::GetOuterListenPort() ); #endif //DS_EPOLL #ifdef USE_NET_TASK #ifndef DS_EPOLL // 激活任务 CNetTask cliTask( pClientReadQueue, pClientWriteQueue, 5*1024 );//与客户端的网络通信任务; //以下监听指定的地址与端口; char selflistenaddr[32]; StructMemSet( selflistenaddr, 0, sizeof(selflistenaddr) ); #ifdef ACE_WIN32 sprintf_s( selflistenaddr, sizeof(selflistenaddr), "%s:%d", CLoadSrvConfig::GetOuterListenAddr(), CLoadSrvConfig::GetOuterListenPort() );//本地监听地址; #else //ACE_WIN32 sprintf( selflistenaddr, "%s:%d", CLoadSrvConfig::GetOuterListenAddr(), CLoadSrvConfig::GetOuterListenPort() );//本地监听地址; #endif //ACE_WIN32 D_INFO( "监听地址:%s...\n", selflistenaddr ); ACE_INET_Addr cliListenAddr( selflistenaddr ); //ACE_INET_Addr cliListenAddr( CLoadSrvConfig::GetOuterListenPort() ); if ( cliListenAddr.is_any() ) { D_ERROR( "错误的监听地址1:%s\n", selflistenaddr ); return 0; } if(cliTask.open((void*)&cliListenAddr) == -1) { D_DEBUG("clitask activate error ,d=%d\n", 1); return 0; } D_INFO( "监听成功!\n" ); #endif //DS_EPOLL CNetTask srvTask(pSrvReadQueue, pSrvWriteQueue);//与服务端的网络通信任务; ACE_INET_Addr srvListenAddr( CLoadSrvConfig::GetListenPort() ); if(srvTask.open((void*)&srvListenAddr) == -1) { D_DEBUG("srvtask activate error ,d=%d\n", 1); return 0; } #else //USE_NET_TASK #ifndef DS_EPOLL // 激活任务 CNetTaskEx cliTask( pClientReadQueue, pClientWriteQueue);//与客户端的网络通信任务; //以下监听指定的地址与端口; char selflistenaddr[32]; StructMemSet( selflistenaddr, 0, sizeof(selflistenaddr) ); #ifdef ACE_WIN32 sprintf_s( selflistenaddr, sizeof(selflistenaddr), "%s:%d", CLoadSrvConfig::GetOuterListenAddr(), CLoadSrvConfig::GetOuterListenPort() );//本地监听地址; #else //ACE_WIN32 sprintf( selflistenaddr, "%s:%d", CLoadSrvConfig::GetOuterListenAddr(), CLoadSrvConfig::GetOuterListenPort() );//本地监听地址; #endif //ACE_WIN32 D_INFO( "监听地址:%s...\n", selflistenaddr ); ACE_INET_Addr cliListenAddr( selflistenaddr ); //ACE_INET_Addr cliListenAddr( CLoadSrvConfig::GetOuterListenPort() ); if ( cliListenAddr.is_any() ) { D_ERROR( "错误的监听地址2:%s\n", selflistenaddr ); return 0; } if(cliTask.Open((void*)&cliListenAddr) == -1) { D_DEBUG("clitask activate error ,d=%d\n", 1); return 0; } D_INFO( "监听成功!\n" ); #endif //DS_EPOLL CNetTaskEx srvTask(pSrvReadQueue, pSrvWriteQueue);//与服务端的网络通信任务; ACE_INET_Addr srvListenAddr( CLoadSrvConfig::GetListenPort() ); if(srvTask.Open((void*)&srvListenAddr) == -1) { D_DEBUG("srvtask activate error ,d=%d\n", 1); return 0; } #endif //USE_NET_TASK #endif //USE_DSIOCP #ifndef DS_EPOLL CManCommHandler< CRcvPkgHandler< CPlayer > >* g_ManCliCommHandler //客户端收包句柄管理; = NEW CManCommHandler< CRcvPkgHandler< CPlayer > >; g_ManCliCommHandler->SetNetQueue( pClientReadQueue );//客户端收包句柄管理,置收包来源(收包队列); g_ManCliCommHandler->SetHandlePoolSize( 5000 );//客户端收包句柄管理,设置收包句柄对象池; #endif //DS_EPOLL CManCommHandler< CRcvPkgHandler< CSrvConn > >* g_ManSrvCommHandler //服务端收包句柄管理; = NEW CManCommHandler< CRcvPkgHandler< CSrvConn > >; g_ManSrvCommHandler->SetNetQueue( pSrvReadQueue );//服务端收包句柄管理,置收包来源(收包队列); g_ManSrvCommHandler->SetHandlePoolSize( 256 );//服务端收包句柄管理,设置收包句柄对象池; ACE_Time_Value serverWaitTime;//等待一会; serverWaitTime.sec(0); serverWaitTime.usec( 2000 ); ConnectAllDbSrv();//连接DbSrv; ACE_OS::sleep( serverWaitTime ); ConnectCenterSrv(); ACE_OS::sleep( serverWaitTime ); ConnectLoginSrv( 0 ); ACE_OS::sleep( serverWaitTime ); ConnectNewLoginSrv(); ACE_OS::sleep( serverWaitTime ); ConnectAllMapSrv();//连接MapSrv; ACE_OS::sleep( serverWaitTime ); ConnectRelationSrv(); ACE_OS::sleep( serverWaitTime ); ConnectShopSrv();//连接shopServer ACE_OS::sleep( serverWaitTime ); ConnectAllRankSrv();//连接RankSrv ACE_OS::sleep( serverWaitTime ); ConnectLogSrv(); //以下主线程继续工作,其间通过pWriteQueue、pReadQueue与网络线程通信; ACE_Time_Value stTime = ACE_OS::gettimeofday(); ACE_Time_Value curTime = ACE_OS::gettimeofday(); ACE_Time_Value pastTime; ACE_Time_Value connectMapsrvTime = ACE_OS::gettimeofday(); ACE_Time_Value connectMapsrvpassed = ACE_OS::gettimeofday() - connectMapsrvTime; D_INFO( "gatesrv:运行中...\n" ); const unsigned long runTime = CLoadSrvConfig::GetRunTime()*1000; while (!g_isGlobeStop) { curTime = ACE_OS::gettimeofday(); pastTime = curTime - stTime; if ( ( runTime>0 ) //runTime == 0 不中断运行; && ( pastTime.msec()>runTime ) ) { #ifndef USE_DSIOCP #ifndef DS_EPOLL cliTask.Quit(); g_pClientSender->SetReadEvent( true );//每轮循环触发一次网络发送; #endif //DS_EPOLL srvTask.Quit(); g_pSrvSender->SetReadEvent( true );//每轮循环触发一次网络发送; #endif //USE_DSIOCP D_DEBUG( "runTime时刻到,退出\n" ); break; } ST_SIG_CATCH { TimerCheck(); ////////////////////////////////////////////////////////////////////////// //检查是否需要因为mapsrv断开而删去所有玩家; #ifndef DS_EPOLL if ( !(g_vecKickMapSrvPlayer.empty()) ) { for ( vector::iterator tmpiter=g_vecKickMapSrvPlayer.begin(); tmpiter!=g_vecKickMapSrvPlayer.end(); ++ tmpiter ) { CManPlayer::KickMapSrvPlayer( *tmpiter ); } g_vecKickMapSrvPlayer.clear(); } #endif //DS_EPOLL //检查是否需要因为mapsrv断开而删去所有玩家; ////////////////////////////////////////////////////////////////////////// #ifndef USE_DSIOCP connectMapsrvpassed = curTime - connectMapsrvTime; if ( connectMapsrvpassed.sec() > 20 )//定时重连mapserver; { connectMapsrvTime = curTime; ConnectAllMapSrv();//连接MapSrv; ConnectAllDbSrv();//连接DbSrv; ConnectCenterSrv();//连接CenterSrv; ConnectLoginSrv( 0 );//连接LoginSrv; ConnectNewLoginSrv(); } #endif //USE_DSIOCP g_pSrvSender->SetReadEvent( false );//每轮循环触发一次网络发送; #ifndef DS_EPOLL g_pClientSender->SetReadEvent( false );//每轮循环触发一次网络发送; #endif //DS_EPOLL //ACE_Time_Value tmpTime;//等待一会; //tmpTime.sec(0); //tmpTime.usec( 1000 ); //ACE_OS::sleep( tmpTime ); //ACE_Thread_Manager::instance()->wait ( &tmpTime, false, false ); #ifndef DS_EPOLL g_ManCliCommHandler->CommTimerProc();//客户端网络消息处理; #endif //DS_EPOLL #ifdef DS_EPOLL pTestManFrame->ManFrameLoop(); #endif //DS_EPOLL g_ManSrvCommHandler->CommTimerProc();//服务端网络消息处理; } END_SIG_CATCH; } #ifndef USE_DSIOCP #ifndef DS_EPOLL cliTask.Quit(); #endif //DS_EPOLL srvTask.Quit(); // 等待任务结束 #ifdef USE_NET_TASK #ifndef DS_EPOLL cliTask.wait(); #endif //DS_EPOLL srvTask.wait(); #else #ifndef DS_EPOLL cliTask.Wait(); #endif //DS_EPOLL srvTask.Wait(); #endif/*USE_NET_TASK*/ #endif //USE_DSIOCP D_INFO( "服务正常结束\n" ); #ifndef DS_EPOLL //删客户端收包管理器; if ( NULL != g_ManCliCommHandler ) { delete g_ManCliCommHandler; g_ManCliCommHandler = NULL; } #endif //DS_EPOLL //删服务端收包管理器; if ( NULL != g_ManSrvCommHandler ) { delete g_ManSrvCommHandler; g_ManSrvCommHandler = NULL; } #ifdef USE_DSIOCP delete cliIocp; cliIocp = NULL; delete srvIocp; srvIocp = NULL; #endif //USE_DSIOCP #ifndef DS_EPOLL //删客户端发送与接收缓冲; if ( NULL != pClientReadQueue ) { delete pClientReadQueue; pClientReadQueue = NULL; } if ( NULL != pClientWriteQueue ) { delete pClientWriteQueue; pClientWriteQueue = NULL; } #endif //DS_EPOLL //删服务端发送与接收缓冲; if ( NULL != pSrvReadQueue ) { delete pSrvReadQueue; pSrvReadQueue = NULL; } if ( NULL != pSrvWriteQueue ) { delete pSrvWriteQueue; pSrvWriteQueue = NULL; } #ifdef USE_DSIOCP //删DsSocket对象池; if ( NULL != g_poolDsSocket ) { delete g_poolDsSocket; g_poolDsSocket = NULL; } if ( NULL != g_poolDsIOBuf ) { delete g_poolDsIOBuf; g_poolDsIOBuf = NULL; } //删唯一对象对象池; if ( NULL != g_poolUniDssocket ) { delete g_poolUniDssocket; g_poolUniDssocket = NULL; } if ( NULL != g_poolPerIOData ) { delete g_poolPerIOData; g_poolPerIOData = NULL; } #endif //USE_DSIOCP #ifndef DS_EPOLL CManPlayer::ReleaseManPlayer(); #endif //DS_EPOLL g_AssignSrvSend.ReleaseAssignSrvSend();//释放assignsrv发包器; //删MsgToPut对象池; if ( NULL != g_poolMsgToPut ) { delete g_poolMsgToPut; g_poolMsgToPut = NULL; } #ifdef DS_EPOLL //if ( NULL != listenSock ) //{ // listenSock->IssueDestory(); // sleep( 2 );//以便在此期间到来的新连接也能被IssueDestory; //} //delete listenSock; listenSock = NULL;//因为它已加入框架,由框架释放; //if ( NULL != pTestManFrame ) //{ // pTestManFrame->IssureDestoryAllEle();//所有sock发起断开; // sleep( 2 );//以便epoll线程close各socket; //} if ( NULL != pEPoll ) { delete [] pEPoll; pEPoll = NULL; } delete pTestManFrame; pTestManFrame = NULL;//dsepoll必须在此之前删除,以防止内存错误; #endif //DS_EPOLL #ifdef DS_EPOLL ReleaseGloblePools(); #endif //DS_EPOLL MainEndTls(); return 0; TRY_END ; return -1; }