I have a TCP Client,which puts a packet in a structure
using System.Runtime.InteropServices;
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct tPacket_5000_E
{
public Int16 size;
public Int16 opcode;
public byte securityCount;
public byte securityCRC;
public byte flag;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I1)]
public byte[] blowfish;
public UInt32 seedCount;
public UInt32 seedCRC;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.I1)]
public UInt32[] seedsecurity;
}
The code I use to put the packet in the structure is:
tPacket_5000_E packet = new tPacket_5000_E();
GCHandle pin = GCHandle.Alloc(data, GCHandleType.Pinned);
packet = (tPacket_5000_E)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(tPacket_5000_E));
pin.Free();
Now,before i continue I must tell you that I'm translating this project from C++ to C#.
This is the problem:
The last 3 members of tPacket_5000_E are Int32(i tried UInt32 too),which is DWORD in C++. The values before those three members,which are NOT Int32,are equal to those in C++.(I inject same packet in both C++ and C# project).
However,those three members have different values.
in C++ the values are(correct):
in C# the values are(incorrect):
The packet in both applications is equal
byte[] data = new byte[] {
0x25, 0x00, 0x00, 0x50, 0x00, 0x00, 0x0E, 0x10,
0xCE, 0xEF, 0x47, 0xDA, 0xC3, 0xFE, 0xFF, 0x79,
0x00, 0x00, 0x00, 0xD1, 0x00, 0x00, 0x00, 0x99,
0xC0, 0x8A, 0x54, 0x78, 0xD3, 0xC4, 0x03, 0xAB,
0x9E, 0x2E, 0x29, 0xE3, 0x5E, 0xEE, 0x4E, 0x6E,
0x20, 0x71, 0x10};
Click here for further information
Why the last three members in the struct are different and how to fix them?
Thanks in advance!
I'd expect that the root of your problem is that the three byte values
public byte securityCount;
public byte securityCRC;
public byte flag;
cause the next 32-bit values not to be word-aligned, and your two sets of code are adding (or not adding) internal padding differently.
I expect that the different packings look something like this:
C++ C# ================================ ================================ [size ][opcode ] [size ][opcode ] [secCnt][secCrc][flag ][blow0 ] [secCnt][secCrc][flag ][blow0 ] [blow1 ][blow2 ][blow3 ][blow4 ] [blow1 ][blow2 ][blow3 ][blow4 ] [blow5 ][blow6 ][blow7 ][seedCou [blow5 ][blow6 ][blow7 ]..PAD... nt ][seedCRC [seedCount ] ][seedSec [seedCRC ] urity0 ][seedSec [seedSecurity0 ] urity1 ][seedSec [seedSecurity1 ] urity2 ][seedSec [seedSecurity2 ] urity3 ][seedSec [seedSecurity3 ] urity4 ] [seedSecurity4 ]
... with C# inserting a byte of padding which causes later values to be one byte off.
You can try using
[StructLayout(LayoutKind.Sequential,Pack=1)]
before your struct definition, which should use the minimum amount of space possible.
Mastering Structs in C# has some good information on how/why this happens.
I suspect that Daniel L is on the right track in his answer.
I would try adding a 4th byte after the flag. My guess is that your C++ compiler is aligning the values on word boundaries. That would "align" the C# version as well.
User contributions licensed under CC BY-SA 3.0