/** * @file OtherserverBase.h * @brief 定义与本服务通信的服务器端其它服务基类 * Copyright(c) 2007,上海第九城市游戏研发部 * All rights reserved * 文件名称: OtherserverBase.h * 摘 要: 定义与本服务通信的服务器端其它服务基类 * 作 者: dzj * 完成日期: 2007.12.10 * */ #include #include "../Utility.h" #include "../BufQueue/BufQueue.h" #include "PacketBuild.h" #pragma once using namespace std; extern IBufQueue* g_pSrvSender; extern unsigned short SELF_SRV_ID;//自身为第几个GateSrv; #ifdef USE_DSIOCP extern TCache< UniqueObj< CDsSocket > >* g_poolUniDssocket;//保存socket唯一对象的对象池; #define CreateServerPkg( PKGTYPE, pPkg ) CPacketBuild::CreatePkg( m_nHandleID, m_nSessionID, m_pUniqueSocket, &pPkg ); #else //USE_DSIOCP #define CreateServerPkg( PKGTYPE, pPkg ) CPacketBuild::CreatePkg( m_nHandleID, m_nSessionID, &pPkg ); #endif //USE_DSIOCP class CSrvBase; /** 服务端各srv连接抽象 与具体srvbase实例一起共同代表一个完整的srv 内部包含指向具体srvbase实例的指针 */ class CSrvConn { public: CSrvConn() : m_nHandleID(0), m_nSessionID(0), m_bySrvType(0x0f)/*0x0ff目前无效的服务标识号*/, m_pSrvBase(NULL), m_bIsDesSelf(false) { #ifdef USE_DSIOCP m_pUniqueSocket = NULL; #endif //USE_DSIOCP }; ~CSrvConn() {}; ///置玩家的句柄信息,每次新建时必须调用; #ifdef USE_DSIOCP public: void SetUniqueDsSocket( UniqueObj< CDsSocket >* pUniqueSocket ) { if ( NULL == pUniqueSocket ) { return; } if ( ( NULL == m_pUniqueSocket ) && ( NULL != pUniqueSocket->GetUniqueObj() ) ) { //自己保存一份,因为MsgToPut中的uniqueSocket在回收时会被删去; m_pUniqueSocket = g_poolUniDssocket->RetrieveOrCreate(); if ( NULL == m_pUniqueSocket ) { TRY_BEGIN; D_ERROR( "SetUniqueDsSocket,g_poolUniDssocket,内存分配失败\n" ); TRY_END; return; } m_pUniqueSocket->Init( pUniqueSocket->GetUniqueObj() ); } } UniqueObj< CDsSocket>* GetUniqueDsSocket() { if ( ( NULL != m_pUniqueSocket ) && ( NULL != m_pUniqueSocket->GetUniqueObj() ) ) { //复制一份往外传,因为MsgToPut中的uniqueSocket在回收时会被删去; UniqueObj< CDsSocket >* pOutUniqueObj = g_poolUniDssocket->RetrieveOrCreate(); if ( NULL == pOutUniqueObj ) { TRY_BEGIN; D_ERROR( "GetUniqueDsSocket,g_poolUniDssocket,内存分配失败\n" ); TRY_END; return NULL; } pOutUniqueObj->Init( m_pUniqueSocket->GetUniqueObj() ); return pOutUniqueObj; } else { return NULL; } } private: UniqueObj< CDsSocket >* m_pUniqueSocket; #endif //USE_DSIOCP public: void SetHandleInfo(/*T_PkgSender* pPkgSender,*/ int nHandleID, int nSessionID ); public: ///设置对应本conn的具体Srv; void SetSrvBase( CSrvBase* pSrvBase ) { m_pSrvBase = pSrvBase; } public: //新建立时的处理(连接建立) void OnCreated() { TRY_BEGIN; ResetInfo(); return; TRY_END; return; } ///销毁时的处理(连接断开) ///注意:在新建连接之前也会调用这里; void OnDestoryed(); ///请求销毁自身(断开连接) void ReqDestorySelf() { TRY_BEGIN; if ( m_bIsDesSelf ) { //已经发过了断开请求,就不再次请求断开了; return; } if ( NULL == g_poolMsgToPut ) { D_WARNING( "CSrvConn::ReqDestorySelf时,g_poolMsgToPut空" ); return; } //发送长度为0消息断开自身; MsgToPut* disconnectMsg = g_poolMsgToPut->RetrieveOrCreate(); if ( NULL == disconnectMsg ) { D_WARNING( "CSrvConn::ReqDestorySelf时,g_poolMsgToPut,内存分配失败" ); return; } #ifdef USE_DSIOCP disconnectMsg->pUniqueSocket = GetUniqueDsSocket();//唯一需要主动设置unisocket者,其余都通过createsrvpkg的方式来生成; #endif //USE_DSIOCP disconnectMsg->nHandleID = m_nHandleID;//向断开执行者传递自身标识; disconnectMsg->nSessionID = m_nSessionID;//向断开执行者传递自身标识; disconnectMsg->nMsgLen = 0;//表明断开连接请求; SendPkgToSrv( disconnectMsg ); m_bIsDesSelf = true;//已经主动请求断开自身; D_WARNING( "本GS主动请求断开SRV(其sessionID:%d)\n", m_nSessionID ); return; TRY_END; return; } ///如果某连接上解析包错误,则断开此连接; void OnPkgError() { //解析包错误时断开连接; ReqDestorySelf(); } ///收包处理; void OnPkgRcved( unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ); ///取句柄ID; int GetHandleID() { return m_nHandleID; } ///取sessionID; int GetSessionID() { return m_nSessionID; } ///向外发包; void SendPkgToSrv( MsgToPut* pPkg ) { TRY_BEGIN; if ( NULL != g_pSrvSender ) { if ( g_pSrvSender->PushMsg( pPkg ) < 0 ) { D_ERROR( "0926dbg, CSrvConn::SendPkgToSrv, PushMsg失败\n" ); } } return; TRY_END; return; } private: ///重置自身信息; void ResetInfo() { m_nHandleID = 0; m_nSessionID = 0; } private: ///通信句柄标识,玩家通过该句柄向发包者标识自己的发包对象; int m_nHandleID; ///通信句柄校验号,玩家通过该校验号向发包者校验自己的发包对象; int m_nSessionID; ///该服务对应的标识号,例如:C、A等,见SrvProtocol.h; unsigned short m_bySrvType; ///对应的具体srv指针; CSrvBase* m_pSrvBase; bool m_bIsDesSelf; }; /** 各具体srv(如db,center,map)的基类 与CSrvConn共同构成完整的srv对象 内部包含指向对应CSrvConn的指针; */ class CSrvBase { private: CSrvBase();//屏蔽此操作; public: ///使用conn构造; explicit CSrvBase( CSrvConn* pConn ) : m_pConn( pConn ) { TRY_BEGIN; if ( NULL != m_pConn ) { m_pConn->SetSrvBase( this ); } TRY_END; }; virtual ~CSrvBase(){}; public: ///取handle; int GetHandleID() { if ( NULL != m_pConn ) { return m_pConn->GetHandleID();//返回连接对应属性; } else { return -1; } } #ifdef USE_DSIOCP UniqueObj< CDsSocket>* GetUniqueDsSocket() { if ( NULL != m_pConn ) { return m_pConn->GetUniqueDsSocket();//返回连接对应属性; } else { return NULL; } } #endif //USE_DSIOCP ///取sessionID; int GetSessionID() { if ( NULL != m_pConn ) { return m_pConn->GetSessionID();//返回连接对应属性; } else { return -1; } } ///向外发包; void SendPkgToSrv( MsgToPut* pPkg ) { if ( NULL != m_pConn ) { m_pConn->SendPkgToSrv( pPkg );//转连接处理; } return; } public: ///断开处理(销毁 ) virtual void OnDestory();//重写此虚函数时小心点,非必要时不要利用此函数,现在centersrv有重写,以后找时间改掉,???,邓子建检查; ///收包处理; virtual void OnPkgRcved( unsigned short wCmd, const char* pBuf, unsigned short wPkgLen ) = 0; protected: void ResetConn() { m_pConn = NULL; }; protected: ///该服务对应的连接; CSrvConn* m_pConn;//该服务对应的连接; };