GS线程

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有联系
时间: 2024-10-25 23:08:48

GS线程的相关文章

再看GS线程

再看GS线程 void GameServer::ProcessThreadTry() { int nCount = 0; packet rcvPkt; rcvPkt.data = new char[1024 * 100]; //该事件工厂主要创建了两个定时器1.livemgr的检测(即是否是有效的连接)2.道具帮会差异更新数据的获取即定时从道具帮会容器中获取差异需要保存到数据库的这个数据 //3.释放队列的处理,现在玩家下线不是直接把channel删除掉而是放到释放队列中等没有数据库访问时在删除

GS(道具,帮会)定时存储

//最近数据库存储做了重大改变,数据库内部的回头再说,先看看GS这边的 1.现在感觉数据库的状态将请求包放入命令队列中,以前是全部放进去,这样让其他的数据库操作不会随着数据库定时器而变慢,GS线程去驱动,一分钟不太可能还存不完 2.差异更新,GS只获取更改了的记录,这样不用每次都把全部的记录都放进去,这个过程是数据库改观不少 外面搞个mgr,内部使用可以重用的模板类,感觉是比之前封装的要好,但复杂度也上去了 m_spSaveOptMgr.reset(new SaveOptMgr(m_spAsyn

服务器线程与包关系(不断跟新)

先画个大概的,思路先理清一下,细节还有很多.这个是服务器比较关键的.其实是只要和地图有关的,GS线程直接扔给map里面,然后接收响应的数据,感觉GS像个桥梁的作用. 服务器线程与包关系(不断跟新),布布扣,bubuko.com

map线程

来看看map线程到底是如何运行的 很早就知道一个map是一个线程,以后有可能改成一个map一个进程,那就先来看看一个map一个线程是如何运作的 其实刚开始整个服务器就是两个线程,但发现这样服务器支持的人数不多,其实我是刚来具体不太清楚到底咋回事,也没有网络进程,最开始就是将GameMap从GameServer中分离出去,单独一个模块 经理说将GameServer相当于一个总闸的作用,相关的map相关的动作放到GameMap里面去做 NEW(Map); class Map : public Map

客户端发包 GS端接收

客户端发包,GS接收 bool GameServer::ProcessLoop(packet& rPkt)//GS线程做的 { if(false == m_spDataLayer->Recv(rPkt)) return true;//没数据了 if(rPkt.is_data) { if(!rPkt.data)//数据为空 return false; GameChannel* pGC = m_vecChannel[rPkt.channel_id];//m_vecChannelGS里面所有玩家的

GS初始化

开启GameServer模式 init函数,现在看看这个大函数干什么的 //这个init也是GameServerUI里面调的,这个线程其实就做了一些初始化的工作,其实这里面没有什么主不主线程,都是在一个进程里面的 void __stdcall GameServer::init() { ///设置最大连接数,现在还不知这个到底干啥的 Share::SetMaxGcNumb(12000); //指定本GS支持的最大数量 ///log日志,现在服务器写日志,在服务器报错的时候可以查看日志,还有报错时生

asynDBcenter(复习)

asynDBCenter asynDBCenter是GS和DBCenter之间的模块,有了他GS访问数据库就是异步的了,以前是同步的,加入某个操作很耗时那么GS就在那等待这个返回值. 1.对于std::queue哪些情况要加锁,哪些不加 push.pop操作100%必须加锁,front和back操作是只读的,不会破坏状态,但是有读写顺序要求时还是要同步. 一般empty和size就不要锁了,对于锁 里面有两个容器 std::queue<CmdPkt> m_queueCmdPkt;//命令包容器

玩家注册登录

简述 C 首先连接AS,当进区的时候AS会发送口令,GS的ip和端口,然后直接登录GS,后面就直接跟GS交互了 AS 负责玩家注册,登录,当玩家进区的时候,生成口令并发送给GS和C GS 接受AS玩家的进区的消息,接受玩家进区 流程图 C AS GS e_c_as_msg_register_req (平台ID,子平台ID,账户,密码) ---------------------------------> e_as_c_msg_register_res (成功or失败) <-----------

项目分析(map复习)

有段时间没看map里面的东西了,刚才看发现功能上增加了一些,在来复习了一次流程初始化每个map建立线程,这个线程有两个功能,1.处理GS发过来的包 2.驱动map里面的定时器GS发过来的包是存在m_gs2msPkts2这个无锁的单消费者,单生产者队列中,只要是GS中不处理的包都要发到MAP中然后每个线程thrTransData::thread()就从m_gs2msPkts2中取包调用Map::process_pkt由于map继承了thrTransData,然后根据绑定调用对于的函数那如果map里