网络请求的回调

在阅读斗地主源码,翻看Component类时,发现这些类中少了网络请求结果的关键逻辑。这些逻辑处理全部都放到了Handler中,但是一直不知道这里的回调是怎么绑定的。

随便找一个Handler类,可以发现Handler类都继承与AMHandler
类中有3个方法,分别为:Run、Handle和GetMessageType
Handle 方法会自动运行Run 虚函数

AMHandler\类 继承与接口IMHandler, 而此类继承与ETModule层中的IMHandler接口

这里的继承关系使得Hotfix层和Mono层具有相同名字的类和方法,来进行统一管理,让作为萌新的我,茅塞顿开

AMHandler\ 类 会在Hotfix中MessageDispatherComponent和ETModule中MessageDispatherComponent类中进行调用

在Hotfix中的MessageDispatherComponent中的Handle函数会被SessionWrap类中调用,这个类初见大佬的视频中讲过是用来做热更新的,先不管它,接着往下看

ETModule中的MessageDispatherComponent类里也调用了IMHandler的Handle方法

到了这里就很清晰了,这个Component的Handle方法会被ClientDispatcher类中的Dispatch调用
ClientDispatcher类中的Dispatch又会被Session中的Run方法调用
源码阅读到这里就非常清晰了


SessionWap & Session 的调用关系

接下来我们去看LandlordsLoginComponent类中的OnLogin方法中Session的创建过程

这里在调用时,Session 会被 SessionWrap类重新封装一层,并保存当前Session的引用
在构造函数中还会添加并注册SessionCallbackComponent的Run、Dispose
按照字面意思去理解,也就是说,当得到结果时会执行SessionWrap 中的Run方法


在Run 方法中有一个比较重要的回调, requestCallback 对象保存的Action对象

当代码执行到Run 时,说明这时候已经拿到了请求的结果,但是这里的Action到底执行的是什么,我们接着往下看

在Call 方法中我们可以看到这里为requestCallback添加了一个Action

结合Run 方法,这里可以理解为,如果此SessionWrap 调用的是这个Call 方法,当请求结果返回时,会调用下面的Action
这里还有一个TaskCompletionSource,我们放到后面说

看完SessionWrap 中的方法,还是不理解一个请求的回调是从哪里来的,这时候我们需要关注Session类,这里从Session被创建时开始看起

Session 有一个StartSystem和一个AwakeSystem,我们现在只关心Start函数中的代码
Start 中只调用了StartRecv函数,下面我们看这里发生了什么

这里的代码非常少,总之就是一个循环的异步,一直去接收

先不管这里的channel是个什么东西,Recv 就是接收的意思,我们接着往下看
当成功接收到消息后,代码会跳到Run 方法中

在Run 方法中,我们别的都不管,只看红框里面的逻辑

if 分支判断中的函数名,命名的非常清楚,如果此消息为客户端的Hotfix消息则执行下面的逻辑,而判断依据为opcode > 10000
到这里我们需要知道,这里的NetworkComponent中MessageDispatcher执行的是那一段代码

这个时候我们又回到了ClientDispatcher类来了,这里我们也只看红框中的代码

当此条消息为Hotfix中时,会取得SessionCallbackComponent,并对MessageCallback进行Invoke,这里的SessionCallbackComponent就是在SessionWrap中添加的那个Component,并对MessageCallback进行了订阅

看到这时,我对NetworkComponent中MessageDispatcher的赋值比较感兴趣,想知道是在哪里对ClientDispatcher进行实例化的

这里的实例化逻辑在NetOuterComponent中,难怪我在NetworkComponent中没有发现任何相关的代码

现在我们回到SessionWrap类中来,还记得之前订阅的MessageCallback吗?当收到回调时,会执行Run 方法

如果flag 为0x01 时,会执行if中的分支,执行之前的action

在SessionWrap中,flag均为0x00,这点也让我很疑惑,询问了一下猫大,Server 会根据此条消息的类型进行分发

在session.Reply() 中会返回0x01
如果消息类型为Actor,则会调用客户端的handler方法

总结

  • 客户端的SessionWrap.Send flag 为0x00
  • 客户端的SessionWrap.Call flag 为0x01 也就是rpc调用

What doesn’t kill you makes you stronger.