消息处理机制

游戏服务器消息处理机制

一般mmo大型游戏都会有多个服务器进程构成,比如 gate、login、scene、world、db、node(进程节点管理也叫服务器管理服)
只有gate与玩家进行交互,gate接到玩家消息会转发到不同服,不同服进行对消息处理,并返回给gate,gate在将消息发给玩家。
消息通常是使用的都是protobuf。


玩家请求消息,以排行为例:
message rankAsk
{
    optional uint64 role_id = 1;
    optional int32 rank_type = 2;
}

message rankReply
{
    optional int32 rank_sort = 1;
    optional int64 rank_score = 2;
}

排行榜的逻辑处理是在world上,gate 获得玩家请求转发给world服,world服需要处理消息并返给gate,在发给玩家

不同进程服通信的消息定义为:
message gate_to_world
{
    optional uint64 player_id = 1;
    optional uint32 msg_id = 2;
    optional bytes msg_body = 3;
}

message world_to_gate
{
    optional uint64 player_id = 1;
    optional uint32 msg_id = 2;
    optional bytes msg_body = 3;    
}

world服收到消息后,反序列化得到 gate_to_world 信息,然后在反序列化msg_body得到玩家的请求消息rankAsk。
处理逻辑,在整合成消息rankReply, 填充到world_to_gate 消息 msg_body里,然后发给gate,转发给玩家。这个消息处理的程序逻辑大致如下:

class Packet
{
public:
    Packet(){}
    Packet(int msgid, ::google::protobuf::Message *msg) : msg_id(msgid), pMsg(msg) {}
    ~Packet()
    {
        if(pMsg)
        {
            delete pMsg;
            pMsg = nullptr;
        }
    }
    int msg_id{-1};
    ::google::protobuf::Message *pMsg{nullptr};
};

class PPacket
{
    virtual Packet* CreatePacket(int msg_id, const char* msg, int msglen) = 0;
};

//解析某个消息处理
template <typename T>
class CPacket : public PPacket
{
public:
    Packet* CreatePacket(int msg_id, const char* msg, int msglen)
    {
        T* t = new T;
        Packet* packet = new Packet();
        t->ParseFromArray(msg, msglen);
        packet->msg_id = msg_id;
        packet->pMsg = t;
        return packet;
    }
};

typedef int (*MsgHandle)(Player*, Packet*);

class MessageMgr
{
public:
    Packet* CreatePacket(int msg_id, const char* msg, int msglen)
    {
        auto it = m_mpacket.find(msg_id);
        if(it != m_mpacket.end())
        {
            return it->second->CreatePacket(msg_id, msg, msglen); //进行消息解析
        }
    }
    MsgHandle GetHandle(int msg_id)
    {
        auto it = m_mhandle->find(msg_id);
        if(it != m_mhandle.end())
        {
            return it->second;
        }
    }
    void registerHandle(int msg_id, MsgHandle handle);
    void registerMsg(int msg_id, PPacket* ppacket);

private:
    std::map<int, MsgHandle> m_mhandle;
    std::map<int, PPacket> m_mpacket;
};

MessageMgr *pMessageMgr;

//每个模块处理每个模块的消息
//这个模块消息可以通过自动生成来完成
class ModuleRank
{
public:
    enum MessageID
    {
        E_RANK_REQ = 1,
    };
    void ReqRank();
    pMessageMgr->registerHandle(E_RANK_REQ, &ModuleRank::ReqRank);
    pMessageMgr->registerMsg(E_RANK_REQ, new CPacket<rankAsk>());
}


消息处理逻辑
gate_to_world_message(const char* msg, int len)
{
    gate_to_world gate_msg;
    gate_msg.ParseFromArray(msg, len);
    int nMsgId = gate_msg.msg_id();
    //解析出玩家的请求消息,排行榜请求
    Packet* packet = pMessageMgr->CreatePacket(nMsgId, gate_msg.msg_body(),gate_msg.msg_body().length());
    MsgHandle handle = pMessageMgr->GetHandle(nMsgId);
    handle(player, packet);  //这里调用ModuleRank::ReqRank 处理消息
}

消息返回则是
world_to_gate_message(int msg_id, const char* msg)
{
    world_to_gate world_msg;
    world_msg.set_msg_id(msg_id);
    world_msg.set_msg_body(msg);
    send_gate(E_WORLD_TO_GATE, world_msg);
}

ModuleRank::ReqRank()
{
    //处理消息逻辑
    //返回消息
    world_to_gate_message(int msg_id, const char* msg);
}

 

参考本人项目实现:

https://github.com/Addision/EventServer/tree/master/Common/packet

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值