c# serialization tcp

C#Deserialización de una estructura después de recibirla a través de TCP



serialization (2)

Estoy enviando mi propio objeto de estructura "paquete" a través de la interfaz TCP que C # ofrece con TCPListener y TCPClient.

Esta es mi estructura

[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(); } }

Estoy usando los métodos de serialización dentro de la estructura para preparar y recuperar los datos antes y después del envío.

Para que el receptor sepa el tamaño de los datos entrantes, agrego algunos datos de encabezado a los bytes que se envían, en el formato de l = 212; ... lo que significa longitud = 212; y el ... es el resto del paquete.

En el extremo receptor, busco esto hasta que encuentro todo l = xxxx; luego hago una nueva matriz de bytes sin el encabezado, luego intento deserializar los datos. El byte del paquete que se usará para la deserialización es: búfer del flujo de tcp. Longitud - foundHeaderSize (l = xxxx;)

Si ejecuto el cliente y el servidor en la misma máquina, funciona sin errores, sin embargo, si tengo el cliente y el servidor en máquinas separadas, obtengo excepciones y se bloquea.

La excepción ocurre cuando el paquete se deserializa, diciendo:

* System.Runtime.InteropServices.SafeArrayTypeMismatchException Se ha producido una discrepancia entre el tipo de tiempo de ejecución de la matriz y el tipo sb registrado en los metadatos en System.Runtime.InteropServices.PtrToStructureHelper

Stacktrace: System.Runtime.InteropServices.PtrToStructureHelper (IntPtr ptr, Object object, Boolean allowValueClasses) en System.Runtime.InteropServices.PtrToStructure (IntPtr ptr, Type structureType .. *

Estoy pidiendo ayuda para identificar la causa del problema. ¿No puedo hacerlo así con los objetos que llegaron a través de la red?


En lugar de tener una cadena que represente la longitud de su paquete y luego restarla por la longitud de la cadena para saber dónde comenzar a leer, debe implementar un prefijo de longitud adecuado. El prefijo de longitud combinado con un encabezado de datos le permitirá leer cada paquete de acuerdo con su tamaño, luego el encabezado de datos lo ayudará a determinar qué hacer con los datos.

El prefijo de longitud ordinaria agrega un encabezado fijo a cada "paquete" que envía. Para crear este encabezado, convierte un número entero (la longitud de sus datos) a bytes, lo que dará como resultado 4 bytes, luego agrega el encabezado de datos después de eso y también el resto del paquete (que son los datos que desea enviar) .

Esto creará la siguiente estructura de paquetes:

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

Leer un paquete es muy simple:

  1. Lea los primeros 4 bytes ( Length ), conviértalos y asígnelos a una variable entera.

  2. Lea el siguiente byte (el encabezado de datos) y colóquelo en una variable.

  3. Lea x bytes en una matriz de bytes (donde x es el entero que declaró en el paso 1).

  4. Use el encabezado de datos del paso 2 para determinar qué hacer con sus datos (la matriz de bytes del paso 3).

En una de mis respuestas anteriores , puede ver un ejemplo de lo que acabo de explicar anteriormente.


Los datos binarios serializados de una estructura pueden diferir según la plataforma y el sistema operativo. por ejemplo, una alineación diferente, un tamaño diferente de largo Esa podría ser la razón por la cual su código funciona en la misma máquina, pero no en una máquina diferente.

Te sugiero que uses una biblioteca como Google ProtoBuf (rápido) https://developers.google.com/protocol-buffers/docs/csharptutorial

o confíe en la serialización de objetos C # usando, por ejemplo, serialización XML (lenta) https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx