ET服务器框架学习笔记(八)
文章目录
前言
这篇文章开始会先介绍与通讯相关的所有类,最后会以一个通信例子来贯穿所有组件类。
接下来以AllServer里面,加载组件的顺序来一一说明
一、ActorMessageSenderComponent
普通Actor消息发送组件,利用这个组件可以获取到一个封装有send功能的类。
1.Actor消息
Actor消息,是ET内部封装的一种消息类型。从定义上来说,我们从ET服务器一个进程发送跨进程的消息,需要知道对方的IP,对方的进程PID,就可以发送过去了。而ET选择的方式是,通过Enity的ActorId,就能直接发给对应的Entity,不管Enity是进程,还是进程上的某个Entity。具体的解释可看:
Actor模型
2.ActorMessageSenderComponent
ActorMessageSenderComponent核心代码如下:
public ActorMessageSender Get(long actorId)
{
if (actorId == 0)
{
throw new Exception($"actor id is 0");
}
IPEndPoint ipEndPoint = StartConfigComponent.Instance.GetInnerAddress(IdGenerater.GetAppId(actorId));
ActorMessageSender actorMessageSender = new ActorMessageSender(actorId, ipEndPoint);
return actorMessageSender;
}
核心点:
- IdGenerater.GetAppId(actorId):通过一个actorId,拿到这个actorId对应所在的Appid,具体实现方式就是在生成actorId时,使用了Appid参与运算,然后通过逆运算得到Appid。
public long ToLong()
{
ulong result = 0;
result |= (uint)this.AppId;
result |= (ulong)this.Value << 18;
result |= (ulong)this.Time << 34;
return (long)result;
}
public IdStruct(long id)
{
ulong result = (ulong)id;
this.AppId = (int)(result & 0x03ffff);
result >>= 18;
this.Value = (ushort)(result & (ushort.MaxValue));
result >>= 16;
this.Time = (uint)result;
}
上面两个方法,都在IdStruct类型中,一个用于生成,一个用于解析。
- StartConfigComponent.Instance.GetInnerAddress():这个方法,通过上面拿到的APPID,结合服务器启动时拿到的启动配置项,从而得到相应APPID对应的IP与端口。
- 实例化一个ActorMessageSender,并返回。
3.ActorMessageSender
在model的ActorMessageSender代码中声明的原始类比较简单,就是将ActorId,与对应的IPEndPoint存放起来。具体功能需要看HOTFIX的ActorMessageSenderHelper对ActorMessageSender类的扩展。
主要扩展了3个方法:Send,Call,CallWithoutException
二、ActorMessageSender
1.Send方法
public static void Send(this ActorMessageSender self, IActorMessage message)
{
Session session = Game.Scene.GetComponent<NetInnerComponent>().Get(self.Address);
message.ActorId = self.ActorId;
session.Send(message);
}
- IActorMessage接口:实现IMessage,在IMessage基础上,增加了ActorId字段
- 扩展的ActorMessageSender.send方法,需要传入一个实现了IActorMessage接口的协议数据类,因为同样实现了IMessage接口,所以也能被前篇里面提到的协议数据转发,以及Handle类进行处理。
- 通过NetInnerComponent组件,拿到对应的Session,同时将ActorMessageSender本身的ActorId赋值给协议数据IActorMessage类中,这样接收方也能拿到这个ActorId,就能知道是谁给他发送这个数据,或者也能通过解析的方式发送回数据
- 通过session.Send发送数据
这里涉及了两个东西:内网组件NetInnerComponent,以及Session
接下来要对这两个类进行详细说明,方便后面流程跑通。
备注:
这里发现ET关于通讯的数据处理基类比较多,就准备单独先对这些类分别记录一下,下篇先记录有关数据流,socket,channel,service等相关数据类,再来说明Session等关联。