游戏服务端之间内部通讯数的据包解析

来源:互联网 发布:淘宝开店身份证照片图 编辑:程序博客网 时间:2024/05/20 05:46
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库中最基础数据的申请
原创粉丝点击