终于到了核心部分之一了——消息机制

既然讲到消息,我们要到消息的源头——客户端

来到Unity.Hotfix的Init文件,并定位到这一句

Game.EventSystem.Run(EventIdType.InitSceneStart);

 他会执行这里的Run代码(不知道为何的去复习ETBook的EventSystem哦)

进入UILoginFactory,他是登录UI的工厂类,在这个工厂将完成一系列的操作

//获取资源组件,用以加载资源
ResourcesComponent resourcesComponent = ETModel.Game.Scene.GetComponent<ResourcesComponent>();
//加载UI的AB包
resourcesComponent.LoadBundle(UIType.UILogin.StringToAB());
//获取到登录UI
GameObject bundleGameObject = (GameObject)resourcesComponent.GetAsset(UIType.UILogin.StringToAB(), UIType.UILogin);
//实例化登录UI
GameObject gameObject = UnityEngine.Object.Instantiate(bundleGameObject);
//在组件工厂创建UI(主要是为了能给游戏物体添加上组件做准备)
UI ui = ComponentFactory.Create<UI, string, GameObject>(UIType.UILogin, gameObject, false);
//为UI添加登录UI组件
ui.AddComponent<UILoginComponent>();

然后我们知道添加一个组件会执行其的Awake函数(如果存在并写明了继承自AwakeSystem的类),我们看到,他在Awake里面从其挂载的ReferenceCollector取得自身子物体的引用,并且为Button添加了点击事件

public void Awake()
{ReferenceCollector rc = this.GetParent<UI().GameObject.GetComponent<ReferenceCollector>();loginBtn = rc.Get<GameObject>("LoginBtn");loginBtn.GetComponent<Button>().onClick.Add(OnLogin);this.account = rc.Get<GameObject>("Account");
}public void OnLogin()
{LoginHelper.OnLoginAsync(this.account.GetComponent<InputField>().text).Coroutine();
}

那么我们去看OnLoginAsync函数 ,知道我为什么在最后空两行吗?(观众:装起来了???)

是因为这里用的await 和 Session.Call方法,await是阻塞方法,在返回结果之前不会继续往下走,而Call是要求有反馈消息的,综上只有在收到消息或者遇到异常才会有可能(异常的话程序将停止运行)执行到R2C_Login reCLogin这里,然后才会走最后一行

// 创建一个ETModel层的Session
ETModel.Session session = ETModel.Game.Scene.GetComponent<NetOuterComponent>().Create(GlobalConfigComponent.Instance.GlobalProto.Address);
// 创建一个ETHotfix层的Session, ETHotfix的Session会通过ETModel层的Session发送消息
Session realmSession = ComponentFactory.Create<Session, ETModel.Session>(session);
//发送登录请求,账号,密码均为传来的参数(理应这样,但这是例子,就无所谓了)
R2C_Login r2CLogin = (R2C_Login) await realmSession.Call(new C2R_Login() { Account = account, Password = "111111" });//释放realmSession
realmSession.Dispose();

注意 第二句的Awake注册了消息回调函数,并且这里的Session是ETHotfix的,与ETModel下的Session有区别

public override void Awake(Session self, ETModel.Session session)
{self.session = session;SessionCallbackComponent sessionComponent = self.session.AddComponent<SessionCallbackComponent>();sessionComponent.MessageCallback = (s, opcode, memoryStream) => { self.Run(s, opcode, memoryStream); };sessionComponent.DisposeCallback = s => { self.Dispose(); };
}

好,既然消息发走了,我们就去看服务端了 

我们直接从NetworkComponent看起吧(事实上客户端和服务端用的是同一个NetworkComponent,所以这里的NetworkComponent组件看完就不需要重复看客户端的了)

// 外网消息组件
Game.Scene.AddComponent<NetOuterComponent, string>(outerConfig.Address);||
\|/
K component = ComponentFactory.CreateWithParent<K, P1>(this, p1, this.IsFromPool);||
\|/
Game.EventSystem.Awake(component, a);||
\|/
[ObjectSystem]
public class NetOuterComponentAwake1System : AwakeSystem<NetOuterComponent, string>
{public override void Awake(NetOuterComponent self, string address){}
}||
\|/
public void Awake(NetworkProtocol protocol, string address, int packetSize = Packet.PacketSizeLength2)
{
}

 因为默认是TCP,所以绑定OnAccept(当收到消息,他会被调用)

public void OnAccept(AChannel channel)||
\|/
//ETModel.Session.cs
public void Awake(AChannel aChannel)||
\|/
注册收到消息回调函数
//ETModel.Session.cs
public void OnRead(MemoryStream memoryStream)||
\|/
//TChannel.cs
public override void Start()||
\|/
开始接收消息
//TChannel.cs
private void StartRecv()||
\|/
接收消息完毕,解析好收到的信息,通过消息回调函数处理消息,
如果是热更层的消息,就调用ETHotfix.Session里注册的回调函数处理,
否则就用ETModel.Session里的函数处理,
(其实两者也是大同小异,大家可以自行查看各个Session的Run函数)
这里面又涉及到消息分发组件MessageDispatcherComponent以及requestCallback的细节,
大家可以自行查看
最后发送消息||
\|/
//TChannel.cs
public void StartSend()

更多细节我会在之后介绍,我们这里的Handler是C2R_LoginHandler.cs

//这里是进行数据库验证,作为例子,这里去掉了验证
//if (message.Account != "abcdef" || message.Password != "111111")
//{
//  response.Error = ErrorCode.ERR_AccountOrPasswordError;
//  reply(response);
//  return;
//}// 随机分配一个Gate
StartConfig config = Game.Scene.GetComponent<RealmGateAddressComponent>().GetAddress();
//Log.Debug($"gate address: {MongoHelper.ToJson(config)}");//读取内部服务器地址
IPEndPoint innerAddress = config.GetComponent<InnerConfig>().IPEndPoint;//从地址缓存中取Session,如果没有则创建一个新的Session,并且保存到地址缓存中
Session gateSession = Game.Scene.GetComponent<NetInnerComponent>().Get(innerAddress);// 向gate服务器请求一个key,客户端可以拿着这个key连接gate
G2R_GetLoginKey g2RGetLoginKey = (G2R_GetLoginKey)await gateSession.Call(new R2G_GetLoginKey() {Account = message.Account});//上述过程已完成,将执行这句,获取外部服务器地址
string outerAddress = config.GetComponent<OuterConfig>().Address2;//设置返回的信息
response.Address = outerAddress;
response.Key = g2RGetLoginKey.Key;
//回复客户端的登录请求
reply(response);

好了,服务端的消息发过来了,我们客户端要响应吧,再回到客户端,这时候r2CLogin已经被赋好值了,可以进行下面的操作了。

ET篇:master消息机制介绍(一般消息的流转)相关推荐

  1. Unity中简单粗暴的消息机制(可限制消息调用次数)

    上代码 /********************************************************文件: EasyMsg.cs作者: 阿飞日期: 2022年02月15日_09: ...

  2. Handler消息机制介绍,流程梳理

    文章目录 前言 基本使用 发送和处理Runnable 发送和处理Message 流程梳理 获取消息 发送消息 消息入队 消息出队 理解 源码分析 前言 Handler 是Android 的消息处理机制 ...

  3. odoo14 mail.thread邮件消息机制(发送消息、字段变化跟踪记录)mail.activity.mixin安排活动

    odoo内部的消息机制是十分便捷的,可以使用odoo 系统消息进行沟通,也可以通过odoo代发邮件进行沟通. 通过点击系统右上角的用户名,在弹出的下拉框中选择 '首选项' ,我们可以设置email选项 ...

  4. android handler的机制和原理_一文搞懂handler:彻底明白Android消息机制的原理及源码

    提起Android消息机制,想必都不陌生.其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行.本篇文章将由浅入深解析Android消息机制的运 ...

  5. windows消息机制详解-3

    1. 引言 Windows 在操作系统平台占有绝对统治地位,基于Windows 的编程和开发越来越广泛. Dos 是过程驱动的,而Windows 是事件驱动的[6],这种差别的存在使得很多Dos 程序 ...

  6. Windows 消息机制浅析

    Windows 消息机制浅析 1.       Windows 的历史 中国人喜欢以史为鉴,而事实也确实是,如果你能知道一件事情的来龙去脉,往往可以更容易地理解事物为什么会表现为当前这样的现状.所以, ...

  7. eCos消息机制学习

    消息机制学习 消息机制介绍 消息机制也是学习eCos平台框架必不可少的一方面,主要负责CGI与各个模块以及各个模块之间的通讯机制,效果与UGW平台相似,但消息机制本身实现方式不同,下图是其整体的流程图 ...

  8. win32mfc————win32消息机制

    文章目录 文章目录 文章目录 前言 一.`消息机制`是什么 二.Windows消息机制 1.产生消息 2.消息传递 3.消息处理 三.基本消息 1.窗口创建消息 2.窗口销毁 3.窗口激活 重要消息 ...

  9. 【安卓学习笔记】Android Handler 消息机制探究

    一.概述 1.android消息机制的含义: Android消息机制,其实指的就是 Handler 的运行机制,而 Handler 要正常运作,又需要底层的 MessageQueue , Looper ...

最新文章

  1. Mybatis实现分库分表
  2. MATLAB-循环类型相关(for while break continue)
  3. 机器人学习--Turtelbot3学习-- Burger与waffle等版本的切换
  4. Ctr点击率预估理论基础及项目实战
  5. 安装python的pip模块
  6. [转]:xmake工程描述编写之选择性编译
  7. gpu跑普通python程序_普通电脑PC怎样跑TensorFlow的GPU模式
  8. WebForm与MVC模式优缺点
  9. vs2017通过ODAC连接oracle11g
  10. excel如何快速查询银行卡号实名认证?
  11. php生成appid,请求认证密钥-AppID
  12. 程序员面试被问,有没有别家的offer?这个问题怎么回答?
  13. CodeForces 1437F Emotional Fishermen(计数dp)
  14. Ubuntu12.10 使用DNW传数据 进行ARM开发板烧写
  15. 以太网采集欧姆龙PLC DM数据并存入ACCESS 使用C#编写上位机程序
  16. lamp +discuz+wordpress+phpmyadmin实例安装详解
  17. 文库自由复制(纯文本)
  18. Java面试:字节跳动+京东+360+网易面试题整理
  19. Oracle实现动态行转列
  20. 火山安卓卡片布局器基本使用方式

热门文章

  1. 微信论坛交流小程序系统毕业设计毕设(4)开题报告
  2. fullCalendar改造计划之带农历节气节假日的万年历
  3. ANDROID物联网开发从入门到实战附源码
  4. VVIC搜款网根据关键词取商品列表 API
  5. 实验六 移位寄存器及其应用
  6. P2P技术详解(一):NAT详解——详细原理、P2P简介
  7. 讲给后台程序员看的前端系列教程(38)——事件处理
  8. 基于HTML美食餐饮文化项目的设计与实现——吃货部落零食12页
  9. 智慧医疗、互联网医疗相关术语
  10. 浅谈微信公众号怎么涨粉丝