void GameServer::ProcessThread() { try {//在ui线程里面搞个大try不是说try效率不好吗,难道只是为了出现错误发现在GS线程里面出现的吗 ProcessThreadTry(); } catch (...) { DWORD dwErrno = GetLastError(); MessageBox(NULL, L"GameServer::process_thread异常", L"异常", MB_OK); } } void GameServer::ProcessThreadTry() { int nCount = 0; packet Pkt; Pkt.data = new char[1024 * 100]; I_TimerFactory* pTimeFactory = GetPlug(TimerFactory);//定时保存还是在这个GS线程里面处理的 for (;;) { ProcMapSendData();//这个相当重要了,处理map发送给GS的数据 m_spAsynDBC->Drive();//驱动数据库回调 m_DBSaveTiming.DriveDBSaveTiming();//驱动定时保存道具,帮会 bool bRcvDataRet = ProcessLoop(Pkt);//收取网络数据并处理 ProcMapSendData();//又在这里处理网络数据,不知这个什么意思,故意这么安排的? if(bRcvDataRet)//缓存里面没有新命令,可以wait一下了 { pTimeFactory->driveTimer(); //等1ms //std::this_thread::sleep_for(std::chrono::milliseconds(1)); ///对于这个曾经机器人总是在上线的时候人老是少,这个问题我找了好久不知什么原因,因为当时对于网络模块不熟, ///但下面这个GC里面没有发送的数据,到GS里面发送,没咋搞懂,GC和GS是在一个线程里面的,应该可以这样做,随后好好看看 /** * [说明]:多进程模式,可能存在未分配成功共享内存而导致发送失败的时候, * 需要GS这边帮未完成发送的GC发送数据,不然可能存在数据丢失的现象, * 注意死循环 */ ////既然空闲了,就看看有没有没发出去的数据 if(m_queGcWait.empty()) { boost::this_thread::interruptible_wait(1); //stl的误差太大,用这个精度高//test2 continue; } int nMaxCount = 5; //最多执行5个GC发送 do //注意别存在死循环 { int nChannelId = m_queGcWait.front(); m_queGcWait.pop(); GameChannel* pGC = m_vecChannel[nChannelId]; if(m_LiveMgr.IsLive(nChannelId) && pGC) //如果改GC在线且活着,则发送未发送成功的数据。 pGC->SendCmdTry(); }while(m_queGcWait.size() && --nMaxCount); } nCount++; if(nCount > 50) { pTimeFactory->driveTimer(); nCount = 0; } } } bool GameServer::ProcessLoop(packet& rPkt) { if(false == m_spDataLayer->Recv(rPkt)) return true;//没数据了 if(rPkt.is_data)///网络是不是数据,有的是libevent事件 { if(!rPkt.data) return false; GameChannel* pGC = m_vecChannel[rPkt.channel_id]; if(pGC) pGC->OnReceiveData(rPkt.data, rPkt.size); m_LiveMgr.OnLive(rPkt.channel_id); } else { //网络事件 link_stat stat = (link_stat)rPkt.size; if (stat == link_stat::link_connected) { GameChannel* pNewGC = new GameChannel(); m_vecChannel[rPkt.channel_id] = pNewGC;//有玩家连接 pNewGC->m_nChannelId = rPkt.channel_id; pNewGC->m_pDataLayer = m_spDataLayer.get(); pNewGC->m_pShare = this; pNewGC->m_pAsynDBC = this->m_spAsynDBC.get(); //gc->m_db = this->m_asyndb->getSynDBptr();//把地址复制一份给GameChannel::m_db,让其具有数据库操作权 m_LiveMgr.Add(rPkt.channel_id); } else if (stat == link_stat::link_disconnected || stat == link_stat::link_connect_failed ) { GameChannel* pDisconnectGC = m_vecChannel[rPkt.channel_id]; if(pDisconnectGC) { //如果进入了地图,保存人物信息时会调用push_freeQueue + 滞空m_Channels[channel_id], pDisconnectGC->OnDisconnect(); //如果未进地图就下线,直接断开;不用保存角色详细数据,可直接放入释放队列中 if(!pDisconnectGC->m_pMap) { //PushFreeQueue(pDisconnectGC); //m_vecChannel[rPkt.channel_id] = NULL; AutoFreeGC(pDisconnectGC); } } m_LiveMgr.Remove(rPkt.channel_id); } } return false; } 这个就是简单的介绍,GS这个模块很重要 GS 数据库 GameMap 网络 跨地图操作(道具,帮会,关系),这些都和GS有联系