我通过TCP接口发送我自己的struct“packet”对象,C#通过TCPListener和TCPClient提供 .
这是我的结构
[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;并且 ... 是数据包的其余部分 .
在接收端,我搜索这个,直到找到整个l = xxxx;然后我创建一个没有 Headers 的新字节数组,然后尝试反序列化数据 . 用于反序列化的数据包字节是:tcp stream的 buffer.Length - foundHeaderSize (l = xxxx;)
如果我在同一台机器上运行客户端和服务器,它可以正常工作,但是如果我在不同的机器上安装客户端和服务器,我会遇到异常并且崩溃 .
数据包被反序列化时发生异常,说:
- System.Runtime.InteropServices.SafeArrayTypeMismatchException数组的运行时类型与System.Runtime.InteropServices.PtrToStructureHelper中元数据中记录的sb类型之间发生不匹配
Stacktrace:System.Runtime.InteropServices.PtrToStructure的System.Runtime.InteropServices.PtrToStructureHelper(IntPtr ptr,Object structure,Boolean allowValueClasses)(IntPtr ptr,Type structureType .. *
我正在寻求帮助以确定问题的原因 . 对于通过网络传输的对象,我不能这样做吗?
2 回答
而不是让字符串表示您的数据包长度,然后减去字符串的长度以知道从哪里开始读取,您应该实现适当的长度前缀 . 长度前缀与数据头相结合将使您能够根据其大小读取每个数据包,然后数据头将帮助您确定如何处理数据 .
普通的长度前缀为您发送的每个“数据包”添加一个固定的标头 . 要创建此标头,您将整数(数据的长度)转换为字节,这将产生4个字节,然后在此之后添加数据标头以及数据包的其余部分(这是您要发送的数据) .
这将创建以下数据包结构:
读取数据包非常简单:
读取前4个字节(
Length
),转换并将它们分配给整数变量 .读取下一个字节(数据头)并将其放入变量中 .
将
x
字节读取到字节数组(其中x
是您在步骤1中声明的整数) .使用步骤2中的数据头确定如何处理数据(步骤3中的字节数组) .
在my previous answers中的一个中,你可以看到我刚才解释的一个例子 .
结构的序列化二进制数据可能因平台和操作系统而异 . 例如不同的对齐方式,不同的长度大小这可能是您的代码在同一台机器上工作的原因,而不是在不同的机器上工作的原因 .
我建议你使用像Google ProtoBuf这样的库(快速)https://developers.google.com/protocol-buffers/docs/csharptutorial
或依赖于使用例如C#对象序列化XML序列化(慢)https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx