遊戲服務端之間內部通訊數的據包解析

DB的包發送結構:
CDataPacket& retPack = allocProtoPacket(dcQuery);    
(1):CDataPacket& CLogicDBReqestHandler::allocProtoPacket(const jxSrvDef::INTERSRVCMD nCmd)
{
    return m_pHost->AllocDataPacket(nCmd);
}

(2):CDataPacket& CDBDataClient::AllocDataPacket(const jxSrvDef::INTERSRVCMD nCmd)
{
    return allocProtoPacket(nCmd);
}

(3):CDataPacket& CCustomJXServerClientSocket::allocProtoPacket(const jxSrvDef::INTERSRVCMD nCmd)
{
    CDataPacket &Packet = allocSendPacket();
    PDATAHEADER pPackHdr;
    //預留通信數據頭空間
    Packet.setLength(sizeof(*pPackHdr));
    Packet.setPosition(sizeof(*pPackHdr));
    pPackHdr = (PDATAHEADER)Packet.getMemoryPtr();
    pPackHdr->tag = DEFAULT_TAG_VALUE;
    //寫入通信消息號
    Packet << nCmd;
    return Packet;
}
(4):    inline CDataPacket& allocSendPacket()
    {
        CDataPacket *pPacket;
        allocSendPacketList(*((CBaseList<CDataPacket*>*)NULL), 0, &pPacket);
        pPacket->setLength(0);
        return *pPacket;
    }
(5):VOID CSendPacketPool::allocSendPacketList(CBaseList<CDataPacket*>& packetList, INT_PTR nAllocCount, CDataPacket **ppSingleAlloc)
{
    static const INT_PTR PacketBlockCountAlgin = 512;
    INT_PTR nCount, nRemainCount;

    m_FreeSendPackList.lock();
    nCount = m_FreeSendPackList.count();

    //從當前空閒列表中拷貝
    if ( nCount > 0 && nAllocCount > 0 )
    {
        nRemainCount = nCount - nAllocCount;
        if ( nRemainCount > 0 )
        {
            packetList.addArray(&m_FreeSendPackList[nRemainCount], nAllocCount);
            m_FreeSendPackList.trunc(nRemainCount);
            nAllocCount = 0;
        }
        else
        {
            //添加現有的
            packetList.addArray(m_FreeSendPackList, nCount);
            m_FreeSendPackList.trunc(0);
            nCount = 0;
        }
        nCount = m_FreeSendPackList.count();
    }
    if ( ppSingleAlloc && nCount > 0 )
    {
        nCount--;
        *ppSingleAlloc = m_FreeSendPackList[nCount];
        m_FreeSendPackList.trunc(nCount);
        ppSingleAlloc = NULL;//將參數置空,以便後續的操作不需要多申請一個
    }

    //仍不足需求數量則繼續申請
    if ( ppSingleAlloc || nAllocCount > 0 )
    {
        //申請數據包對象內存塊
        INT_PTR i, nNewCount = __max(PacketBlockCountAlgin, nAllocCount);
        //如果還需要申請一個單獨的數據包,則增加需求數量
        if ( ppSingleAlloc ) nNewCount ++;
        nNewCount = (nNewCount + PacketBlockCountAlgin) & (~(PacketBlockCountAlgin - 1));
        CDataPacket *pPacket = (CDataPacket*)m_Allocator.AllocBuffer(sizeof(*pPacket) * nNewCount);
        //講數據包集的內存塊添加到數據內存頭列表中
        //m_SendPacketMemList.add(pPacket);
        //如果空閒發送送數據列表的剩餘空間不足以放下新申請的數據包,則增長空閒發送數據包列表的保留長度
        if ( m_FreeSendPackList.maxCount() < nCount + nNewCount )
            m_FreeSendPackList.reserve(nCount + nNewCount);
        //循環調用構造函數
        for (i=0; i<nNewCount; ++i)
        {
            new(pPacket)CDataPacket(&m_Allocator);
            m_FreeSendPackList[nCount] = pPacket;//將數據包保存到空閒發送送數據列表
            pPacket++;
            nCount++;
        }
        //將剩餘申請的數據包拷貝到申請列表中
        if ( nAllocCount > 0 ) 
        {
            nCount -= nAllocCount;
            packetList.addArray(&m_FreeSendPackList[nCount], nAllocCount);
            m_FreeSendPackList.trunc(nCount);
        }
        //需要申請一個單獨的數據包
        if ( ppSingleAlloc )
        {
            nCount--;
            *ppSingleAlloc = m_FreeSendPackList[nCount];
            m_FreeSendPackList.trunc(nCount);
        }
    }
    m_FreeSendPackList.unlock();
}

引擎的DB發送結構:
    CDataPacket& DataPacket = m_pEntity->AllocPacket(AP);
(1):#ifdef _DEBUG
CDataPacket&  CActor::_AllocPacket(CActorPacket &pack, LPCSTR file, INT_PTR line)
#else
CDataPacket&  CActor::AllocPacket(CActorPacket &pack)
#endif
{
#ifdef _DEBUG
    Assert(GetCurrentThreadId() == GetLogicServer()->GetLogicEngine()->getThreadId());
    Assert(FALSE == InterlockedCompareExchange(&g_boPacketAlreadyAlloced, TRUE, FALSE));
    g_sPacketAllocFile = file;
    g_nPacketAllocLine = line;
#endif
    CLogicGate* logicgate = (CLogicGate*)GetLogicServer()->GetGateManager()->getGate(m_nGateID);
    //CDataPacket* pSendToGatePacket = NULL;
    pack.packet = logicgate->GetSendToGatePacket();
    //Assert(&pack.packet);
    //OutputMsg(rmTip,"AllocPacket =%d",pack.packet->getOffsetPtr());
    if(!m_isInited)
    {
#ifdef _DEBUG
    OutputMsg(rmError,"AllocData when actor not inited,file=%s,line=%d",file,(int)line);
#else
    OutputMsg(rmError,"AllocData when actor not inited");
#endif


        //如果是調試版本直接掛掉服務器
    }
    pack.packet->reserve(pack.packet->getPosition()+sizeof(GATEMSGHDR));

    PGATEMSGHDR pHdr = (PGATEMSGHDR)pack.packet->getOffsetPtr();//保留協議頭部分

    pack.nHdrPos = pack.packet->getPosition();

    pHdr->dwGateCode    = RUNGATECODE;
    pHdr->nSocket    = m_nUserSocket;
    pHdr->wSessionIdx= (WORD)m_nGateSessionIndex;
    pHdr->wIdent        = GM_DATA;
    pHdr->wServerIdx = m_nServerSessionIndex;
    pHdr->nDataSize = 0;
    pHdr->wTemp = RUNTEMPCODE;
    pHdr->tickCount = _getTickCount();
    pack.packet->adjustOffset(sizeof(GATEMSGHDR));
    pack.pActor = this;    
    return *pack.packet;
}
會話的發送結構:
 CDataPacket &out = allocProtoPacket(sCheckPasswdResult);
(1):直接引用基類函數:CDataPacket& CCustomJXServerClientSocket::allocProtoPacket(const jxSrvDef::INTERSRVCMD nCmd)
{
    CDataPacket &Packet = allocSendPacket();
    PDATAHEADER pPackHdr;
    //預留通信數據頭空間
    Packet.setLength(sizeof(*pPackHdr));
    Packet.setPosition(sizeof(*pPackHdr));
    pPackHdr = (PDATAHEADER)Packet.getMemoryPtr();
    pPackHdr->tag = DEFAULT_TAG_VALUE;
    //寫入通信消息號
    Packet << nCmd;
    return Packet;
}
(2):VOID CCustomJXServerClientSocket::flushProtoPacket(CDataPacket& packet)
{
    PDATAHEADER pPackHdr = (PDATAHEADER)packet.getMemoryPtr();
    //計算並向協議頭中寫入通信數據長度
    INT_PTR nDataSize = packet.getLength() - sizeof(*pPackHdr);

    if(nDataSize >65535)
    {
        WORD   wHead= *(WORD*)((char*)packet.getMemoryPtr() + sizeof(*pPackHdr));
        OutputMsg(rmError,"嚴重錯誤CCustomJXServerClientSocket::flushProtoPacket 數據長度%d過長,head=%d",(int)nDataSize,(int)wHead);
    }
    pPackHdr->len = (WORD)nDataSize;
    flushSendPacket(packet);
}

總結:通過內存池申請包,發送包放到緩衝列表,線程從緩衝列表拿到數據進行轉發。再進行解析,獲取數據.數據獲取
完畢以後還要返回給內存池,


通用包結構:

其它發給引擎的話一般用到的是:CustomJXServerClientSocket.cpp這個文件的申請
引擎發給引擎的話一般用到的是:CustomJXClientSocket.cpp這個文件的申請(因爲發送給不同客戶的)

武藝lib庫中最基礎數據的申請
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章