/// <summary> /// 序列化消息包。 /// </summary> /// <typeparam name="T">消息包类型。</typeparam> /// <param name="packet">要序列化的消息包。</param> /// <param name="destination">要序列化的目标流。</param> /// <returns>是否序列化成功。</returns> public bool Serialize <T>(T packet, Stream destination) where T : Packet { PacketBase packetImpl = packet as PacketBase; if (packetImpl == null) { Log.Warning("Packet is invalid."); return(false); } if (packetImpl.PacketType != PacketType.ClientToServer) { Log.Warning("Send packet invalid."); return(false); } m_CachedStream.SetLength(m_CachedStream.Capacity); // 此行防止 Array.Copy 的数据无法写入 m_CachedStream.Position = 0L; CSPacketHeader packetHeader = ReferencePool.Acquire <CSPacketHeader>(); Serializer.Serialize(m_CachedStream, packetHeader); ReferencePool.Release(packetHeader); Serializer.SerializeWithLengthPrefix(m_CachedStream, packet, PrefixStyle.Fixed32); ReferencePool.Release((IReference)packet); m_CachedStream.WriteTo(destination); return(true); }
/// <summary> /// 序列化消息包 /// </summary> /// <typeparam name="T">消息包类型</typeparam> /// <param name="packet">消息包对象</param> /// <returns></returns> public byte[] Serialize <T>(T packet) where T : Packet { PacketBase packetImpl = packet as PacketBase; if (packetImpl == null) { Log.Warning("Packet is null."); return(null); } if (packetImpl.PacketType != PacketType.ClientToServer) { Log.Warning("Packet type is invalid."); return(null); } // 恐怖的 GCAlloc,这里是例子,不做优化 using (MemoryStream stream = new MemoryStream()) { //跳过消息头长度(8)的位置开始序列化消息内容 stream.Position = PacketHeaderLength; Serializer.SerializeWithLengthPrefix <T>(stream, packet, PrefixStyle.Fixed32); //回头再来序列化消息包头 stream.Position = 0; CSPacketHeader header = ReferencePool.Acquire <CSPacketHeader>(); header.Id = packet.Id; header.PacketLength = (int)stream.Length - PacketHeaderLength; //Log.Info("序列化的id:" + header.Id); //Log.Info("序列化的包体长度:" + header.PacketLength); //方式1:直接写入字节数据id+packetLen stream.Write(BitConverter.GetBytes(header.Id), 0, 4); stream.Write(BitConverter.GetBytes(header.PacketLength), 0, 4); //方式2:用头部结构体序列化进去(暂时没测通过) //Serializer.SerializeWithLengthPrefix(stream, header, PrefixStyle.Fixed32); ReferencePool.Release <CSPacketHeader>(header); return(stream.ToArray()); } }