ET服务器框架学习笔记(六)

ET服务器框架学习笔记(六)


OpcodeTypeComponent

接下来开始记录下ET的通讯相关的系统,这个系统比较庞大,估计要分好多篇文章记录,一点一点来吧。


一、OpcodeTypeComponent是什么?

我们知道通讯肯定要有通讯的数据(貌似是废话),通讯最底层是二进制的流,我们通讯的方式主要就是将我们认识的数据结构,变成二进制,发到目的地,然后再将二进制还原的过程,具体可以看下TCP/IP的七层通讯协议。
既然协议需要提前订好,那么通讯需要的数据结构也得提前定义好,要不然怎么知道对方发过来的是个什么东西呢。
OpcodeTypeComponent组件的功能就是管理所有通信需要用到的协议数据结构。他将所有定义好的通讯数据结构全部放到自己内部,进行统一管理,这样方便查询,序列化与反序列化数据结构。我们知道ET管理类的方式主要是利用特性与反射,这里也不例外,我们先看一个例子:

[Message(InnerOpcode.M2M_TrasferUnitRequest)]
	public partial class M2M_TrasferUnitRequest: IRequest
	{
		public int RpcId { get; set; }

		public Unit Unit { get; set; }

	}

重点看特性:[Message(InnerOpcode.M2M_TrasferUnitRequest)],其中InnerOpcode.M2M_TrasferUnitRequest是一个枚举,也就是协议号,可以理解为一个id对应一个数据结构。
接下来看看OpcodeTypeComponentLoadSystem,根据之前的经验,直接看代码:

[ObjectSystem]
	public class OpcodeTypeComponentLoadSystem : LoadSystem<OpcodeTypeComponent>
	{
		public override void Load(OpcodeTypeComponent self)
		{
			self.Load();
		}
	}

即当Game.Scene.AddComponent();之后,会调用OpcodeTypeComponentLoadSystem的Load,然后调用到OpcodeTypeComponent的Load。先不看Load里面做了啥,先看看OpcodeTypeComponent有什么数据。

二、OpcodeTypeComponent的数据

1.管理的数据

  • DoubleMap<ushort, Type> opcodeTypes:DoubleMap又是一个ET封装的数据结构,他的代码比较简单,就是一个双向KV的字典,内部还封装了转成List的各种方法。
  • Dictionary<ushort, object> typeMessages:字典类,从定义上看应该是一个协议ID对应一个object的。
    接下来再看LOAD代码,从而分析出这两个结构主要是用来管理什么内容的

2.Load()

代码如下(示例):

public void Load()
		{
			this.opcodeTypes.Clear();
			this.typeMessages.Clear();
			
			List<Type> types = Game.EventSystem.GetTypes(typeof(MessageAttribute));
			foreach (Type type in types)
			{
				object[] attrs = type.GetCustomAttributes(typeof(MessageAttribute), false);
				if (attrs.Length == 0)
				{
					continue;
				}
				
				MessageAttribute messageAttribute = attrs[0] as MessageAttribute;
				if (messageAttribute == null)
				{
					continue;
				}

				this.opcodeTypes.Add(messageAttribute.Opcode, type);
				this.typeMessages.Add(messageAttribute.Opcode, Activator.CreateInstance(type));
			}
		}

代码比较简短,写法和之前的EventSystem比较类似。可以看到主要内容:

  • 清理自身的两个数据结构内的所有数据
  • 从EventSystem中拿到所有带有MessageAttribute标签特性的类信息,对于上面的例子就是拿到了M2M_TrasferUnitRequest类的类型信息、
  • 遍历所有的类型信息,进行一些基础判定,然后将对应的协议号与类型信息都存入到this.opcodeTypes中进行管理,this.opcodeTypes.Add(messageAttribute.Opcode, type);
  • 实例化对应的类型,并将其与协议号一一对应,存入this.typeMessages进行管理,this.typeMessages.Add(messageAttribute.Opcode, Activator.CreateInstance(type));
    经过上述步骤后,知道opcodeTypes存放的是协议号与协议类型的类型信息,typeMessages存放的是协议号与实例化的协议类型实例。
    有了这两个数据结构之后,我们能很方便的从协议类型-协议号-协议类型信息,之间进行转换。

# 三、OpcodeTypeComponent的方法 OpcodeTypeComponent相关的方法都比较简单,都是一些查找方法: - 通过类型信息获取协议号:
public ushort GetOpcode(Type type)
		{
			return this.opcodeTypes.GetKeyByValue(type);
		}
  • 通过协议号获取类型信息:
public Type GetType(ushort opcode)
		{
			return this.opcodeTypes.GetValueByKey(opcode);
		}
  • 通过协议号获取类型实例
		public object GetInstance(ushort opcode)
		{
#if SERVER
			Type type = this.GetType(opcode);
			if (type == null)
			{
				// 服务端因为有人探测端口,有可能会走到这一步,如果找不到opcode,抛异常
				throw new Exception($"not found opcode: {opcode}");
			}
			return Activator.CreateInstance(type);
#else
			return this.typeMessages[opcode];
#endif
		}

上面这里需要注意的地方在于,区别了客户端和服务器。客户端利用了上面的typeMessages,缓存了协议数据类型,实现0GC,而服务器由于协议跨协程(源代码写的),我个人认为是会跨进程通信,所以反射实例化一个协议数据类。

总结

这篇主要记录的是ET通信里面的基础协议数据类如果管理,下篇应该是消息转发,派发相关内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值