- 因为所有的网络消息在发送时候格式都是这样
- 对于用Protobuf定义的每一消息类型class,都需要定义一个对应消息头code
- 在发送的时候,先将消息体进行序列化,再将code进行序列化,进行组装发送
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();
ushort 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++;
}
}
}