protobuf-net无法反序列化我的课程

我想序列化一个’Player’类,并通过我的网络流发送给客户端。

球员类

[ProtoMember(1)] public int flag; [ProtoMember(2)] public Int16 id; [ProtoMember(3)] public MyVector3 CharPos; [ProtoMember(7)] public bool spawned; 

MyVector3 (由于protobuf不支持Vector3序列化这一事实)

 [ProtoContract] public class MyVector3 { [ProtoMember(4)] public float X { get; set; } [ProtoMember(5)] public float Y { get; set; } [ProtoMember(6)] public float Z { get; set; } public MyVector3() { this.X = 0.0f; this.Y = 0.0f; this.Z = 0.0f; } public MyVector3(float x, float y, float z) { this.X = x; this.Y = y; this.Z = z; } public static implicit operator Vector3(MyVector3 v) { return new Vector3(vX, vY, vZ); } public static implicit operator MyVector3(Vector3 v) { return new MyVector3(vX, vY, vZ); } } 

序列化和反序列化函数

 public byte[] serialize(Object obj) { if (obj == null) { return null; } MemoryStream ms = new MemoryStream(); Serializer.SerializeWithLengthPrefix(ms,obj,PrefixStyle.Base128); return ms.ToArray(); } public Player deserialize(NetworkStream inc) { Player obj = Serializer.DeserializeWithLengthPrefix(inc,PrefixStyle.Base128); return obj; } 

测试function(实际上不起作用!)

  static void Main(string[] args) { TcpListener serverSocket = new TcpListener(8888); TcpClient clientSocket = default(TcpClient); Serialize ser = new Serialize(); Player temp = new Player(); serverSocket.Start(); while (true) { clientSocket = serverSocket.AcceptTcpClient(); using (NetworkStream networkStream = clientSocket.GetStream()) { DeserializeTest(ser,networkStream); SerializeTest(ser, networkStream); } } } static void SerializeTest(Serialize ser,NetworkStream networkStream) { Player temp = new Player(); BinaryWriter writer = new BinaryWriter(networkStream); writer.Write(ser.serialize(temp)); networkStream.Flush(); } static void DeserializeTest(Serialize ser, NetworkStream networkStream) { Player temp = new Player(); temp = (Player)ser.deserialize(networkStream); Console.WriteLine(temp.flag.ToString() + temp.CharPos.ToString()); networkStream.Flush(); } } 

现在发生了什么:

DeserializeTest启动时,protobuf尝试从networkStream反序列化数据,整个函数类型“冻结”并开始循环。 当我只是序列化数据(在客户端中)并将其发送到反序列化的服务器(此代码)时,一切都像魅力一样。

网络流在关闭之前不会结束, 默认情况下, protobuf(由Google定义)会消耗到流的末尾。 它正在等待更多数据,或者您的流最终结束。 如果要发送多条消息,或者只是想保持流打开,则使用SerializeDeserialize替换SerializeWithLengthPrefixDeserializeWithLengthPrefix 。 这将添加额外的信息,以便在不关闭流的情况下获取单个消息。 重要的是管道的两端都知道它们正在使用这种变体。


完整示例(这是使用核心.NET,但现在应该没有问题翻译):

 using System; using System.IO; using System.Net.Sockets; using System.Threading; using ProtoBuf; [ProtoContract] public class Player { [ProtoMember(1)] public int flag; [ProtoMember(2)] public Int16 id; [ProtoMember(3, DataFormat = DataFormat.Group)] public MyVector3 CharPos; [ProtoMember(7)] public bool spawned; } public struct MyVector3 { public readonly float X, Y, Z; public MyVector3(float x, float y, float z) { X = x; Y = y; Z = z; } public override string ToString() { return string.Format("({0},{1},{2})", X, Y, Z); } } static class Program { static ManualResetEvent evt = new ManualResetEvent(false); static void Main(string[] args) { var player = new Player() {CharPos = new MyVector3(1, 2, 3), flag=123, id=456, spawned=true}; ThreadPool.QueueUserWorkItem(x => { Console.WriteLine("client: waiting for server"); evt.WaitOne(); Console.WriteLine("client: opening connection"); using (var client = new TcpClient("localhost", 15000)) using (var ns = client.GetStream()) { serialize(ns, player); ns.Flush(); Console.WriteLine("client: wrote player"); Console.WriteLine("client: waiting for response"); while (ns.ReadByte() >= 0) { Console.WriteLine("client: receiving..."); } Console.WriteLine("client: connection closed by server"); ns.Close(); } }); TcpListener serverSocket = new TcpListener(15000); TcpClient clientSocket; serverSocket.Start(); Console.WriteLine("server: accepting connections"); evt.Set(); while (true) { Console.WriteLine("server: waiting for client..."); clientSocket = serverSocket.AcceptTcpClient(); Console.WriteLine("server: got client"); using (NetworkStream networkStream = clientSocket.GetStream()) { var fromNetwork = deserialize(networkStream); Console.WriteLine("server: got player"); Console.WriteLine("> flag: {0}", fromNetwork.flag); Console.WriteLine("> id: {0}", fromNetwork.id); Console.WriteLine("> spawned: {0}", fromNetwork.spawned); Console.WriteLine("> pos: {0}", fromNetwork.CharPos); } } } public static void serialize(Stream dest, Player player) { if (player == null) throw new ArgumentNullException(); Serializer.SerializeWithLengthPrefix(dest, player, PrefixStyle.Base128); } public static Player deserialize(Stream inc) { Player obj = Serializer.DeserializeWithLengthPrefix(inc, PrefixStyle.Base128); return obj; } } 

这给出了:

 client: waiting for server server: accepting connections server: waiting for client... client: opening connection server: got client client: wrote player client: waiting for response server: got player > flag: 123 > id: 456 > spawned: True > pos: (1,2,3) client: connection closed by server server: waiting for client...