• GS与MS之间通信


    GS与MS之间通信
    注意GS与MS是两个线程,现在是每个map一个线程,他们之间是内部协议进行通信的,那既然是两个线程那如何通信呢,看了net进程通信这个就比较简单了
    举个例子
    m_pMap->Gs2MsData(gs2ms_add_player, m_nChannelId, (void*)&rActorEx, sizeof(rActorEx));//发送玩家上线包
    void Map::Gs2MsData(int cmd, int channel_id, void* data, int len)
    {
        MapPkt pkt;
        pkt.channelId = channel_id;
        pkt.data = m_memPool.popPkt(len);注意这个m_memPool是线程安全的队列,内部是boost无锁队列实现的
        memcpy(pkt.data, data, len);//不同线程需要内存拷贝,不可能使用同一块地址
        pkt.len = len;
        pkt.cmd = cmd;
    
        PushPkt(pkt);
    }
    
    void ThrTransData::PushPkt(MapPkt Pkt)
    {
        for (;;)
        {
            if(m_gs2msPkts2.push(Pkt))//将包放入boost无锁队列中
                break;
            cxx11::this_thread::interruptible_wait(1);
        }
    }
    那看看MS这边是如何取的
    在share初始化的时候开启了一个线程,这个线程可以说整个map的数据都是这里面处理的
    bool ThrTransData::GetDataFromQueue(MapPkt* pPkt)
    {
        if(m_gs2msPkts2.empty())
            return false;
        {
            MapPkt tmpPkt;
            if(m_gs2msPkts2.pop(tmpPkt))//从GS到MS这端的无锁队列中取包
            {
                *pPkt = tmpPkt;
                return true;
            }
            return false;
        }
        return true;
    }
    if(GetDataFromQueue(&Pkt))
    {
        ProcessPkt(Pkt);//解析包调用相应函数
        m_memPool.pushPkt(Pkt.data, Pkt.len);//将内存池归还
    
        nCount++;
        if(nCount > 30)
        {
            nCount = 0;
            m_spTimerFactory->driveTimer();
        }
        continue;
    }
    //至此从GS到MS这边的包就是这样处理的
    
    那从MS到GS的包
    从Map需要发到GS的包也不多,还有一种通过GS转到map的
    SendCmd2Gs(ms2gs_prop_mgr, nChannelID, pData, nLen);
    void SendCmd2Gs(int nCmd, int nChannelId, void* pData, int nLen)
    {
        MapPkt Pkt;
        Pkt.cmd = nCmd;
        Pkt.channelId = nChannelId;
        char* pszNewBuffer = new char[nLen];//这个是自己new的,发送到MS是从内存池中获取的
        memcpy(pszNewBuffer, pData, nLen);
        Pkt.data = pszNewBuffer;
        Pkt.len = nLen;
        PushData2GS(Pkt);
    };
    
    void PushData2GS(const MapPkt& Pkt)
    {
        while(1)
        {
            if(m_quePkts2Gs.push(Pkt))//从MS发送到GS的队列
        }
    }
    那GS是如何去的呢
    void Share::ProcMapSendData()//这个是GS驱动的
    {
        if(!itMap.second->RecvData(Pkt))//从无锁队列中取包
            break;
        if(Pkt.cmd == ms2gs_转client_cmd)//针对包进行处理
        {
            OnTurnToClient(Pkt.channelId, Pkt.data, Pkt.len);
        }
    }
    //开来发包都是双向的,需要两个队列,这个在net那边也是的
    //其次就是需要额外的内存放到队列中,因为不可能去操作同一块内存的,要么自己new,要么从内存池中分配
    //MS与GS之间通过MapPkt进行通信,对于客户端和服务器通过protocol通信,通常是自己定义一块buf,然后打包到BUF中,net那块也是在内存池中分配一块然后存储这个buf,因为这个buf也是公用的
    //刚开始不懂程序就是这些内存问题没有搞清楚
  • 相关阅读:
    工作的价值
    面对伤害该不该回击
    建议
    利用私有的API获得手机上所安装的所有应用信息(包括版本,名称,bundleID,类型)
    你必须知道的HTTP错误
    静态库制作
    MDM证书申请的流程
    IOS客户端实现RSA加密
    获得appstore里面app的最新的版本信息,进行版本更新
    C语言实现简单php自定义扩展
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/4176047.html
Copyright © 2020-2023  润新知