客户端发送消息到逻辑服务器的网关,再转发消息到db服务器,接着异步返回到逻辑服务器,再返回到客户端。
本文内容:
1、客户端到逻辑服务器的请求消息
2、从数据服务器返回到逻辑服务器的响应
1、客户端到逻辑服务器的请求消息
接收处理线程的例行函数
void* ExecSockDataMgr::RecvDataProcessRoutine(ExecSockDataMgr *pRunData)
{
......
//处理客户端发送的数据包
pRunData->ProcessUserRecvPacket( pSession, pPacket->getOffsetPtr(), (int)pPacket->getAvaliableLength() );
......
}
VOID ExecSockDataMgr::ProcessUserRecvPacket(PRUNGATEUSERSESSION pSession, char *pBuffer, int nBufferSize)
{
......//检查包头校验码和消息长度
DispatchUserRecvPacket(pSession, pSession->RecvBuf.lpBuffer + sizeof(*pPackHdr), pPackHdr->wPacketSize);
......
}
网关的消息请求
VOID CLogicGate::DispatchUserRecvPacket(PRUNGATEUSERSESSION pSession, char *pBuffer, uint32 nBufferSize)
{
......
case common::NetCmd::cQueryCharList:
{
if (pSession->btUserState != eGUSSelChar)
return;
HandleUserQueryChar(pSession);
}
break;
......
}
派送消息到逻辑服务器的db连接线程
VOID CLogicGate::HandleUserQueryChar(PRUNGATEUSERSESSION pSession)
{
common::SERVERUSERHANDLE UsrHdl;//服务器间通信的用户句柄
UsrHdl.llSocket = pSession->nSocket;
UsrHdl.wUserIndex = pSession->nIndex;
UsrHdl.nVerify = pSession->nVerifyIdx;
UsrHdl.wGateIndex = m_nGateIndex;
//派送到db线程的发送请求队列
g_DBManager->requestQueryChar(&UsrHdl, pSession->nAccountId);
}
其中:
服务器之间通信数据包中传递的用户句柄
* 如:客户端在逻辑服务器查询角色、创建角色等操作需要由
* 逻辑服务器转发给DB服务器,未能使逻辑服务器在DB服务器
* 返回数据后知晓是返回给那个客户端的消息,逻辑服务器会在
* 通信数据包中包含客户端句柄,DB服务器也会在返回的数据包
* 中返回此句柄。
struct ServerUserHandle
{
unsigned long long llSocket;//socket
unsigned short wGateIndex;//网关索引
unsigned short wUserIndex;//网关用户索引
int nVerify;//校验码
};
typedef ServerUserHandle SERVERUSERHANDLE, *PSERVERUSERHANDLE;
void CDBManager::requestQueryChar(common::SERVERUSERHANDLE *pUserHandle, int nAccountId)
{
CDataPacket &packet = AllocProtoPacket(common::DBType::dcQueryCharList);
packet << *pUserHandle;
packet << nAccountId;
FlushProtoPacket(packet);
}
2、从数据服务器返回到逻辑服务器的响应
数据服务器和逻辑服务器异步过程返回的异步数据类型
struct SynergyData
{
common::SERVERUSERHANDLE userHandle;
enum OPType
{
aorLogin = 1,//登陆返回
aorQueryCharList,//查询角色列表返回
aorCreateChar,//创建角色返回
aorDeleteChar,//删除角色返回
aorEnterGame,//进入游戏返回
}opType;
union
{
struct {
int nErrorCode;
int nUserId;
}login;//登录返回
struct {
int nCharCount;
CPoolDataPacket *pPacket;
}querychar;//查询角色列表返回
struct {
int nErrorCode;
CPoolDataPacket *pPacket;
}createchar;//创建角色返回
struct {
int nErrorCode;
}deletechar;//删除角色返回
struct {
int nErrorCode;
}enterGame;//进入游戏返回
};
};
(1)db连接线程处理返回的消息
服务器之间的连接线程的消息队列 派送的消息包
//逻辑服务器的db线程派送消息
void CDBManager::DispatchRecvPacket(CDataPacketReader &inPacket)
{
common::NetPacketMessage msg(0);
inPacket >> msg;
switch(msg.wMsg)
{
......
case common::DBType::dsSendCharList:
HandleQueryCharListRet(inPacket);
break;
...
}
获取对应的网关来派送
void CDBManager::HandleQueryCharListRet(CDataPacketReader &inPacket)
{
common::SERVERUSERHANDLE userHandle;
int nAccountId, nCharCount;
inPacket >> userHandle;
inPacket >> nAccountId;
inPacket >> nCharCount;
CLogicGate *pGate = g_GateManager->getGate(userHandle.wGateIndex);
if (pGate)
{
CPoolDataPacket *pRetPack = m_DataPacketPool.allocPacket();
pRetPack->writeBuf(inPacket.getOffsetPtr(), inPacket.getAvaliableLength());
pGate->resultUserQueryCharList(&userHandle, nCharCount, pRetPack);
}
}
//添加到异步响应队列
void CLogicGateSynergy::resultUserQueryCharList(const common::SERVERUSERHANDLE *pUserHandle, int nCharCount, CPoolDataPacket *pPacket)
{
SynergyData data;
data.userHandle = *pUserHandle;
data.opType = SynergyData::aorQueryCharList;
data.querychar.nCharCount = nCharCount;
data.querychar.pPacket = pPacket;
m_SynergyDataList.append(data);
}
(2)数据接收处理线程处理异步返回的消息
在数据接收处理线程的循环里处理db连接线程的发来的异步响应消息
void* ExecSockDataMgr::RecvDataProcessRoutine(ExecSockDataMgr *pRunData){
......
while ( !pRunData->m_boStoping )
{
......
//调用例行执行函数
pRunData->OnRecvThreadSingleRun(dwProcStartTick);
......
}
VOID CLogicGate::OnRecvThreadSingleRun(TICKCOUNT dwCurrTick)
{
super::OnRecvThreadSingleRun(dwCurrTick);
ProcessSynergyList();
}
void CLogicGateSynergy::ProcessSynergyList()
{
m_SynergyDataList.flush();//异步消息队列
INT_PTR i, nCount = m_SynergyDataList.count();
for (i=0; i<nCount; ++i)
{
HandleSynergyData(&m_SynergyDataList[i]);
}
m_SynergyDataList.clear();
}
处理异步数据
void CLogicGate::HandleSynergyData(SynergyData *pData)
{
DispatchSynergyData(pData);
DestroySynergyData(pData);
}
网关提交消息到网关的发送队列,准备发送消息到客户端
void CLogicGate::DispatchSynergyData(SynergyData *pData)
{
PRUNGATEUSERSESSION pSession;
//检查用户有效性,确保用户未过期
if (pData->userHandle.wUserIndex >= m_SessionList.count())
return;
pSession = m_SessionList[pData->userHandle.wUserIndex];
if (!pSession || pSession->nSocket != (int)pData->userHandle.llSocket\
|| pSession->nVerifyIdx != pData->userHandle.nVerify)
return;
switch(pData->opType)
{
case SynergyData::aorQueryCharList:
{
CGateSendPacket &packet = AllocSendPacket(pSession->nIndex);
packet.writeCmd(common::SystemId::sysLogin, common::NetCmd::sSendCharList);
packet << pData->querychar.nCharCount;
packet.writeBuf(pData->querychar.pPacket->getMemoryPtr(), pData->querychar.pPacket->getLength());
pData->createchar.pPacket->freeBack();
packet.flush();
}
break;
......
}
}