02.GeekServer的序列化分析
2024.02.23 需求
GeekServer当前版本:
commit a0ccffd89617ecf0f0400a6c4ff34328c62c7fed (HEAD -> main, origin/main, origin/HEAD)
Author: lixiuzhi <1642267742@qq.com>
Date: Thu Nov 9 15:22:29 2023 +0800
修复生成agent wrapper没有处理partial class的情况
TcpServer -> Client
- 数据结构:
- 消息长度 (Int)
- 消息MsgId (Int)
- 消息体 (Message)
- 写入:
TcpChannel.cs
public override void Write(Message msg)
{
if (IsClose())
return;
var bytes = Serializer.Serialize(msg);
int len = 8 + bytes.Length;
Span<byte> span = stackalloc byte[len];
int offset = 0;
span.WriteInt(len, ref offset);
span.WriteInt(msg.MsgId, ref offset);
span.WriteBytesWithoutLength(bytes, ref offset);
lock (sendStream)
{
sendStream.Write(span);
}
sendSemaphore.Release();
}
- 读取:
ClientTcpChannel.cs
protected virtual bool TryParseMessage(ref ReadOnlySequence<byte> input)
{ var reader = new SequenceReader<byte>(input);
if (!reader.TryReadBigEndian(out int length) || reader.Remaining < length - 4)
{return false;
}
var payload = input.Slice(reader.Position, length - 4);
if (payload.Length < 4)
throw new Exception("消息长度不够");
//消息id
reader.TryReadBigEndian(out int msgId);
var msgType = MsgFactory.GetType(msgId);
if (msgType == null)
{ LOGGER.Error($"消息ID:{msgId} 找不到对应的Msg.");
} else
{
var message = MessagePackSerializer.Deserialize<Message>(payload.Slice(4));
#if UNITY_EDITOR
Debug.Log("收到消息:" + MessagePackSerializer.SerializeToJson(message));
#endif
if (message.MsgId != msgId)
{ throw new Exception($"解析消息错误,注册消息id和消息无法对应.real:{message.MsgId}, register:{msgId}");
}
onMessage(message);
} input = input.Slice(input.GetPosition(length));
return true;
}