遊戲服務端之間內部通訊數的據包解析
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庫中最基礎數據的申請
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.