Question

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):

  1. seedCount:0x00000079
  2. seedCRC:0x000000d1
  3. SeedSecurity:
  4. -[0]:0x548ac099
  5. -1:0x03c4d378
  6. -[2]:0x292e9eab
  7. -[3]:0x4eee5ee3
  8. -[4]:0x1071206e

in C# the values are(incorrect):

  1. seedCount:0xd1000000
  2. seedCRC:0x99000000
  3. SeedSecurity:
  4. -[0]: 0x78548ac0
  5. -1: 0xab03c4d3
  6. -[2]: 0xe3292e9e
  7. -[3]: 0x6e4eee5e
  8. -[4]: 0x00107120

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!

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top