- 因为所有的网络消息在发送时候格式都是这样

- 对于用Protobuf定义的每一消息类型class,都需要定义一个对应消息头code
- 在发送的时候,先将消息体进行序列化,再将code进行序列化,进行组装发送
//这个代码没有进行过优化,会产生严重GC,不要复制使用。这里只是作为演示static byte[] PackMsg(IMessage msg){byteCollection.Clear();var code = Dispatch.GetOpCode(msg.GetType());byteCollection.AddRange(BitConverter.GetBytes(code));byteCollection.AddRange(msg.ToByteArray());return byteCollection.ToArray();}
- 我这里使用的code是
ushort类型,只占用两个字节,用BitConverter可以方便转换
问题
- 产生问题在于,protobuf是先定义
.proto文件,然后根据这个文件来生成.cs文件 - 如果直接在生成的
.cs文件里面给每个消息类标记Message[Opcode.Login]会产生问题 - 就是每次修改
.proto文件重新生成的时候,会导致标记的opCode被覆盖。

- 但是还好他生成是分部类,ET框架就利用这点把消息类分成两部分,一部分是消息体,一部分是定义opCode和自己的接口这些

- 但是我比较懒,我不想写那么多。直接通过反射获取所有类型,并且按照遍历顺序给每一个打一个ID就是了
- 客户端和服务端使用同一个程序集,所以序号也是一样的。
- 但是潜在的问题是
- 1.必须把客户端和服务端的消息类型定义在一起
static void GetAllMessageType(){var assembly = Assembly.GetExecutingAssembly();//注意这里标记开始codeushort startIndex = 1;foreach (var type in assembly.GetTypes()){if (type.Namespace == nameof(Message) && type.GetInterface(nameof(IMessage)) != null){msgTable.Add(startIndex, type);msgInstanceTable.Add(startIndex, (IMessage)Activator.CreateInstance(type));startIndex++;}}}