GS发包到MS(GS,MS包交互过程) 例:人物上线 首先看看其实如何确定是哪张地图的 数据库首先只保存一个mapid 在share初始化的时候已经初始化了所有map,并保存了map的指针信息,其key就是mapid if(rActorEx.GetMapID() <= 0) rActorEx.SetMapID(1009); int mapID = rActorEx.GetMapID(); rActorEx.m_nBodyID = m_pShare->TGetnBodyId(rActorEx.GetProf(), rActorEx.GetSex());//现在那个bodyid用到了 m_pMap = m_pShare->GetMapByMapId(mapID);//通过mapid就能获得map指针信息 if(!m_pMap) { m_ActorId = 0; return; } m_pMap->Gs2MsData(gs2ms_add_player, m_nChannelId, (void*)&rActorEx, sizeof(rActorEx));//传入MS,m_pMap即玩家所在地图指针 void Map::Gs2MsData(int cmd, int channel_id, void* data, int len) { MapPkt pkt; pkt.channelId = channel_id; pkt.data = m_memPool.popPkt(len);//从内存池中分配一块内存出来,以前用的new,然后这个new很容易失败的 memcpy(pkt.data, data, len); pkt.len = len; pkt.cmd = cmd; PushPkt(pkt); } //接下来就是起的线程的作用了 void ThrTransData::PushPkt(MapPkt Pkt) { #ifdef BOOST_LOCKFREE for (;;) { if(m_gs2msPkts2.push(Pkt))//将这个包放入无锁队列中 break; cxx11::this_thread::interruptible_wait(1); } #else { cxx11::lock_guard lock(m_mtxGs2Ms); m_queGs2MsPkts.push(Pkt); } #endif }; void ThrTransData::ThreadLoop() { //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); MapPkt Pkt; try { int nCount = 0; while (true) { if(GetDataFromQueue(&Pkt))//从无锁队列中取包 { ProcessPkt(Pkt); m_memPool.pushPkt(Pkt.data, Pkt.len); nCount++; if(nCount > 30) { nCount = 0; m_spTimerFactory->driveTimer(); } continue; } { m_spTimerFactory->driveTimer(); if (m_bStopWork) break; cxx11::this_thread::interruptible_wait(1); } } } catch(...) { char szMsg[256] = {0}; sprintf(szMsg, "【%s】线程%dMap :Pkt.cmd = %d", __FUNCTION__, ::GetCurrentThreadId(), Pkt.cmd); safe::error_msg(szMsg); } } void Map::ProcessPkt(MapPkt pkt) { //... //gs2ms_add_player属于GS与MS通信的内部协议,内部协议采用树的形式,平行关系就太多了管理不方便 else if(gs2ms_add_player == pkt.cmd)//玩家进入地图消息,仅仅是个小例子 { PlayerChannel* pPC = new PlayerChannel(this);//这个PlayerChannel是很大的一个模块,玩家信息,回头再看 //加到地图中,但是并未激活该玩家 int nChannelId = pPC->OnPlayerEnter(pkt.data, pkt.len); m_vecPlayerChannel[nChannelId] = pPC; AddPlayer(nChannelId); } //... }