UN2L4——区分消息类型
不同类型的消息辨识问题
当将序列化的2进制数据发送给对象时,对方如何区分?举例:
-
PlayerInfo
:玩家信息
-
ChatInfo
:聊天信息
-
LoginInfo
:登录信息
等等
这些数据对象序列化后是长度不同的字节数组,将它们发送给对象后,对方如何区分出他们分别是什么消息
如何选择对应的数据类反序列化它们?
区分消息思路
解决方案:为发送的信息添加标识,比如添加消息ID
在所有发送的消息的头部加上消息ID(int
、short
、byte
、long
都可以,根据实际情况选择)
举例说明:
消息构成,如果选用int
类型作为消息ID的类型,前4个字节为消息ID,而后面的字节为数据类的内容
这样每次收到消息时,先把前4个字节取出来解析为消息ID,再根据ID进行消息反序列化即可
区分消息的关键点,是在数据字节数组头部加上消息ID,只要前后端定义好统一的规则
那么我们可以通过ID来决定如何反序列化消息,并且可以决定我们应该如何处理该消息
实现
实践步骤
- 创建消息基类,基类继承
BaseData
,基类添加获取消息ID的方法或者属性
- 让想要被发送的消息继承该类,实现序列化反序列化方法
- 修改客户端和服务端收发消息的逻辑
消息基类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class BaseMessage : BaseData { public override int GetBytesNum() { throw new System.NotImplementedException(); }
public override int Reading(byte[] bytes, int BeginIndex = 0) { throw new System.NotImplementedException(); }
public override byte[] Writeing() { throw new System.NotImplementedException(); }
public virtual int GetID() { return 0; } }
|
继承消息基类的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| public class PlayerData : BaseData { public string name; public int atk; public int lev;
public override int GetBytesNum() { return 4 + 4 + 4 + Encoding.UTF8.GetBytes(name).Length; }
public override int Reading(byte[] bytes, int beginIndex = 0) { int index = beginIndex; name = ReadString(bytes, ref index); atk = ReadInt(bytes, ref index); lev = ReadInt(bytes, ref index); return index - beginIndex; }
public override byte[] Writeing() { int index = 0; byte[] bytes = new byte[GetBytesNum()]; WriteString(bytes, name, ref index); WriteInt(bytes, atk, ref index); WriteInt(bytes, lev, ref index); return bytes; } }
public class PlayerMessage : BaseMessage { public int playerID; public PlayerData playerData;
public override byte[] Writeing() { int index = 0; byte[] bytes = new byte[GetBytesNum()]; WriteInt(bytes, GetID(), ref index); WriteInt(bytes, playerID, ref index); WriteData(bytes, playerData, ref index); return bytes; }
public override int Reading(byte[] bytes, int beginIndex = 0) { int index = beginIndex; playerID = ReadInt(bytes, ref index); playerData = ReadData<PlayerData>(bytes, ref index); return index - beginIndex; }
public override int GetBytesNum() { return 4 + 4 + playerData.GetBytesNum(); }
public override int GetID() { return 1001; } }
|
服务端部分代码:
1 2 3 4 5 6 7
| PlayerMessage msg = new PlayerMessage(); msg.playerID = 666; msg.playerData = new PlayerData(); msg.playerData.name = "我是唐老狮的服务端"; msg.playerData.atk = 99; msg.playerData.lev = 50; socketClient.Send(msg.Writeing());
|
客户端部分代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| byte[] receiveBytes = new byte[1024]; int receiveNum = socket.Receive(receiveBytes);
int msgID = BitConverter.ToInt32(receiveBytes, 0); switch (msgID) { case 1001: PlayerMessage msg = new PlayerMessage(); msg.Reading(receiveBytes, 4); print(msg.playerID); print(msg.playerData.name); print(msg.playerData.atk); print(msg.playerData.lev); break; }
|