Вопрос

У меня есть TCP-клиент, который помещает пакет в структуру

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;
}

Код, который я использую для помещения пакета в структуру:

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

Прежде чем продолжить, я должен сказать вам, что я перевожу этот проект с C++ на C#.

Это проблема:

Последние три члена tPacket_5000_E — это Int32 (я тоже пробовал UInt32), который в C++ представляет собой DWORD.Значения перед этими тремя членами, которые НЕТ Int32 аналогичны пакетам в C++. (Я добавляю один и тот же пакет как в проект C++, так и в проект C#).

Однако эти три участника имеют разные ценности.

в C++ значения такие(правильный):

  1. семяКаунт: 0x00000079
  2. семяCRC: 0x000000d1
  3. СидБезопасность:
  4. -[0]:0x548ac099
  5. -1:0x03c4d378
  6. -[2]:0x292e9eab
  7. -[3]:0x4eee5ee3
  8. -[4]:0x1071206e

в C# значения(неправильный):

  1. семяКаунт: 0xd1000000
  2. семяCRC: 0x99000000
  3. СидБезопасность:
  4. -[0]:0x78548ac0
  5. -1:0xab03c4d3
  6. -[2]:0xe3292e9e
  7. -[3]:0x6e4eee5e
  8. -[4]:0x00107120

Пакет в обоих приложениях одинаковый

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};

Нажмите здесь для получения дополнительной информации

Почему последние три члена структуры отличаются и как их исправить?

Заранее спасибо!

Это было полезно?

Решение

Я ожидаю, что корень вашей проблемы в том, что трехбайтовые значения

public byte securityCount;
public byte securityCRC;
public byte flag;

приведет к тому, что следующие 32-битные значения не будут выровнены по словам, и ваши два набора кода по-разному добавляют (или не добавляют) внутреннее заполнение.

Я ожидаю, что разные упаковки будут выглядеть примерно так:

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                 ]

...с C#, вставляющим байт заполнения, что приводит к отклонению последующих значений на один байт.

Вы можете попробовать использовать

[StructLayout(LayoutKind.Sequential,Pack=1)]

перед определением структуры, которое должно использовать минимально возможный объем пространства.

Освоение структур в C# имеет некоторую полезную информацию о том, как и почему это происходит.

Другие советы

Я подозреваю, что Дэниел Л. находится на правильном пути в своем ответе.

Я бы попробовал добавить 4-й байт после флага.Я предполагаю, что ваш компилятор C++ выравнивает значения по границам слов.Это также «выровняет» версию C#.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top