I have a struct defined as
[StructLayout(LayoutKind.Sequential,Pack=1)]
private struct networkMessage
{
public messageType type;
public string message;
}
and I have this function to convert the struct into byte[]
private byte[] ConvertToByteArray(networkMessage inStruct)
{
int structSize = Marshal.SizeOf(inStruct);
byte[] byteArray = new byte[structSize];
IntPtr memPtr = IntPtr.Zero;
try
{
memPtr = Marshal.AllocHGlobal(structSize);
Marshal.StructureToPtr(inStruct, memPtr, false);
Marshal.Copy(memPtr, byteArray, 0, structSize);
}
finally
{
if (memPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(memPtr);
}
}
foreach (byte b in byteArray)
{
Console.WriteLine(b + " ");
}
return byteArray;
}
and this to convert back into a struct
private networkMessage ConvertFromByteArray(byte[] inByte)
{
foreach (byte b in inByte)
{
Console.WriteLine(b);
}
GCHandle handle = GCHandle.Alloc(inByte, GCHandleType.Pinned);
networkMessage outStruct = (networkMessage) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(networkMessage)); //---Exception here
return outStruct;
}
This in use for a TCP application which both acts as a server and client, such that the same executable runs on both machines. Testing the conversion in the objects constructor shows it working fine, but a byte array coming from another computer causes an access violation exception. Printing out the bytes on both systems shows they are the same. What could be the problem? I assume this might have something to do with the struct?
This can't work.
Try this: Set message
to a string much longer than 16 characters and then look at the value of Marshal.SizeOf(inStruct)
. It will be 12 for a 64-bit version and 8 for a 32 bit version - regardless of the length of message
.
The correct solution to this is to use serialization to convert the data.
You might want to check out NetTcpBinding
, which can use DataContracts to serialize the data.
Also, have a look at JSON serialization.