C#通过TCP接收它后反序列化结构

我通过C#提供的TCP接口和TCPClient通过TCP接口发送自己的struct“packet”对象。

这是我的结构

[Serializable] struct RemuseNetworkPacket { public String ApplicationCode; public String ReceiverCode; public RemusePacketType Type; public uint ID; public uint cID; public String Name; public byte[] Data; public String Text; public System.Drawing.Point Coords; public String Timestamp; public String Time; public String SenderName; public byte[] Serialize() { var buffer = new byte[Marshal.SizeOf(typeof(RemuseNetworkPacket))]; var gch = GCHandle.Alloc(buffer, GCHandleType.Pinned); var pBuffer = gch.AddrOfPinnedObject(); Marshal.StructureToPtr(this, pBuffer, false); gch.Free(); return buffer; } public void Deserialize(byte[] data) { var gch = GCHandle.Alloc(data, GCHandleType.Pinned); this = (RemuseNetworkPacket)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(RemuseNetworkPacket)); gch.Free(); } } 

我正在使用结构内的序列化方法来准备和检索发送前后的数据。

为了让接收者知道传入的数据的大小,我给正在发送的字节添加一些标题数据,格式为l = 212; …这意味着长度= 212; 而是数据包的其余部分。

在接收端我search这个,直到我find整个l = xxxx; 然后我做一个没有头的新的字节数组,然后尝试反序列化数据。 用于反序列化的数据包字节是:tcp stream的buffer.Length – foundHeaderSize (l = xxxx;)

如果我在同一台机器上运行客户机和服务器,它可以正常工作,但是如果我在不同的机器上有客户机和服务器,我会遇到exception并崩溃。

当数据包被反序列化时发生exception,并说:

* System.Runtime.InteropServices.SafeArrayTypeMismatchExceptionarrays的运行时types与System.Runtime.InteropServices.PtrToStructureHelper元数据中logging的sbtypes之间发生不匹配

StackTrace:System.Runtime.InteropServices.PtrToStructureHelper(IntPtr ptr,对象结构,布尔allowValueClasses)在System.Runtime.InteropServices.PtrToStructure(IntPtr ptr,typesstructureType .. *

我正在寻求帮助,以确定问题的原因。 我能否通过networking传来的对象来做到这一点?

而不是有一个string代表你的包长度,然后减去string的长度知道从哪里开始阅读,你应该实现适当的长度前缀 。 长度前缀与数据头结合在一起使您能够根据数据包的大小读取每个数据包,然后数据头将帮助您确定如何处理数据。

普通的长度前缀为您发送的每个“数据包”添加一个固定的头文件。 为了创build这个头文件,你需要将一个整数(你的数据的长度)转换成字节,这会得到4个字节,然后在这之后添加数据头,还有剩下的数据包(这是你想发送的数据) 。

这将创build以下数据包结构:

 [Length (4 bytes)][Header (1 byte)][Data (x byte(s))] 

读取数据包非常简单:

  1. 读取前4个字节( Length ),转换并将它们分配给一个整型variables。

  2. 读取下一个字节(数据头)并将其放入一个variables中。

  3. x个字节读取到一个字节数组(其中x是您在步骤1中声明的整数)。

  4. 使用步骤2中的数据头来确定如何处理数据(步骤3中的字节数组)。

我以前的答案之一中,你可以看到上面我刚刚解释的一个例子。

根据平台和操作系统,结构的序列化二进制数据可能会有所不同。 例如不同的alignment,不同长度的大小这可能是你的代码在同一台机器上工作,而不是在另一台机器上工作的原因。

我build议你要么使用像Google ProtoBuf(快速)的图书馆https://developers.google.com/protocol-buffers/docs/csharptour

或依赖于使用例如XML序列化(慢)的C#对象序列化https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx