acotor模型理解2-客户端向服务器发送actor消息

actor消息:

[Message(OuterOpcode.Actor_Test)]
    [ProtoContract]
    public partial class Actor_Test: IActorMessage
    {
        [ProtoMember(90, IsRequired = true)]
        public int RpcId { get; set; }

        [ProtoMember(93, IsRequired = true)]
        public long ActorId { get; set; }

        [ProtoMember(1, IsRequired = true)]
        public string Info;

    }

客户端:

private void OnSend()
        {
            // 发送一个actor消息
            ETModel.SessionComponent.Instance.Session.Send(new Actor_Test() { Info = "message client->gate->map->gate->client" });
        }

服务器:

一,网关服务器:

1,OuterMessageDispatcher:

收到消息,判断是否是actor消息,用ActorMessageSender发送actor消息,

case IActorMessage iActorMessage: // gate session收到actor消息直接转发给actor自己去处理
                {
                    long unitId = session.GetComponent<SessionPlayerComponent>().Player.UnitId;//获取map服务器的unit的unitid
                    ActorMessageSender actorMessageSender = Game.Scene.GetComponent<ActorMessageSenderComponent>().Get(unitId);//根据unitid获取ActorMessageSender,ActorMessageSender包含了根据map服务器的unit的unitid得到的mapsession,来让ActorMessageSender知道发送到哪个服务器
                    actorMessageSender.Send(iActorMessage);向这个服务器发送actor消息
                    return;
                }

二,map服务器:

1,InnerMessageDispatcher:map服务器,

收到网关服务器消息,进行分发,放入map服务器的MailBox里

public class InnerMessageDispatcher: IMessageDispatcher
    {
        public void Dispatch(Session session, Packet packet)
        {
            IMessage message;
            try
            {
                Type messageType = Game.Scene.GetComponent<OpcodeTypeComponent>().GetType(packet.Opcode);
                message = (IMessage)session.Network.MessagePacker.DeserializeFrom(messageType, packet.Bytes, packet.Offset, packet.Length);
            }
            catch (Exception e)
            {
                // 出现任何解析消息异常都要断开Session,防止客户端伪造消息
                Log.Error(e);
                session.Error = ErrorCode.ERR_PacketParserError;
                session.Network.Remove(session.Id);
                return;
            }
            
            
            // 收到actor消息,放入actor队列
            if (message is IActorMessage iActorMessage)
            {
                Entity entity = (Entity)Game.EventSystem.Get(iActorMessage.ActorId);//根据ActorId获取到map服务器上的unit
                if (entity == null)
                {
                    Log.Warning($"not found actor: {iActorMessage.ActorId}");
                    ActorResponse response = new ActorResponse
                    {
                        Error = ErrorCode.ERR_NotFoundActor,
                        RpcId = iActorMessage.RpcId
                    };
                    session.Reply(response);
                    return;
                }
    
                MailBoxComponent mailBoxComponent = entity.GetComponent<MailBoxComponent>();//获取unit上的MailBox
                if (mailBoxComponent == null)
                {
                    ActorResponse response = new ActorResponse
                    {
                        Error = ErrorCode.ERR_ActorNoMailBoxComponent,
                        RpcId = iActorMessage.RpcId
                    };
                    session.Reply(response);
                    Log.Error($"actor没有挂载MailBoxComponent组件: {entity.GetType().Name} {entity.Id}");
                    return;
                }
                
                mailBoxComponent.Add(new ActorMessageInfo() { Session = session, Message = iActorMessage });//放入MailBox转发消息
                return;
            }
            
            Game.Scene.GetComponent<MessageDispatherComponent>().Handle(session, new MessageInfo(packet.Opcode, message));
        }
    }

2,MailBoxComponent,map服务器,邮箱来处理actor消息

public static async void HandleAsync(this MailBoxComponent self)
        {
            ActorMessageDispatherComponent actorMessageDispatherComponent = Game.Scene.GetComponent<ActorMessageDispatherComponent>();
            
            long instanceId = self.InstanceId;
            
            while (true)
            {
                if (self.InstanceId != instanceId)
                {
                    return;
                }
                try
                {
                    ActorMessageInfo info = await self.GetAsync();
                    // 返回null表示actor已经删除,协程要终止
                    if (info.Message == null)
                    {
                        return;
                    }

                    // 根据这个actor的类型分发给相应的ActorHandler处理
                    await actorMessageDispatherComponent.ActorTypeHandle(self.ActorType, (Entity)self.Parent, info);//根据ActorType来判断是哪一个ActorTypeHandler来处理actor消息(CommonActorTypeHandler或者GateSessionActorTypeHandler),这里的actor消息是CommonActorTypeHandler。怎么判断是哪种actor消息呢?gate session收到的actor消息是GateSessionActorTypeHandler来处理,其他服务器是CommonActorTypeHandler来处理
                }
                catch (Exception e)
                {
                    Log.Error(e);
                }
            }
        }

3,CommonActorTypeHandler,map服务器,来处理map服务器的actor消息

public class CommonActorTypeHandler : IActorTypeHandler
    {
        public async Task Handle(Session session, Entity entity, IActorMessage actorMessage)
        {
            await Game.Scene.GetComponent<ActorMessageDispatherComponent>().Handle(session, entity, actorMessage);//执行actor消息的对应的处理函数,
        }
    }

4,Actor_TestHandler,map服务器,是Actor_Test消息的处理函数

public class Actor_TestHandler : AMActorHandler<Unit, Actor_Test>
    {
        protected override async Task Run(Unit unit, Actor_Test message)
        {
            Log.Debug(message.Info);

            long gateSessionId= unit.GetComponent<UnitGateComponent>().GateSessionActorId;//这里获取到gate服务器上,客户端的sessionid。
            ActorMessageSender gateSender = Game.Scene.GetComponent<ActorMessageSenderComponent>().GetWithActorId(gateSessionId);//根据客户端的sessionid创建向gate服务器发送actor消息的ActorMessageSender,作用是map服务器-gate服务器,
            Actor_TestGate msg=new Actor_TestGate();
            msg.Info = message.Info;
            gateSender.Send(msg);//向gate服务器发送actor消息
            //await Task.CompletedTask;
        }
    }

5,InnerMessageDispatcher,gate服务器收到actor消息的处理函数

6,MailBoxComponent,gate服务器,邮箱来处理actor消息

7,GateSessionActorTypeHandler,gate服务器,收到actor消息将消息发给客户端

总结:客户端发来 IActorMessage,处理流程是:

客户端-gate服务器-map服务器-gate服务器-客户端

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值