C# 구조에서 잘못된 멤버를 주문합니다
-
22-08-2019 - |
문제
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의 마지막 3 명의 멤버는 int32 (나도 UINT32를 시도 했음)이며 C ++의 DWORD입니다. 그 세 멤버 앞의 가치 아니다 int32는 C ++의 것과 동일합니다 (나는 C ++ 및 C# 프로젝트 모두에서 동일한 패킷을 주입).
그러나이 세 멤버는 다른 값을 가지고 있습니다.
C ++에서 값은 다음과 같습니다.옳은):
- SeedCount : 0x00000079
- seedcrc : 0x000000d1
- Seendsecurity :
- -[0] : 0x548AC099
- -1: 0x03C4D378
- -[2] : 0x292E9EAB
- -[3] : 0x4eee5ee3
- -[4] : 0x1071206E
C#에서 값은 (잘못된):
- SeedCount : 0xD1000000
- seedcrc : 0x99000000
- Seendsecurity :
- -[0] : 0x78548AC0
- -1: 0xab03c4d3
- -[2] : 0xE3292E9E
- -[3] : 0x6e4eee5e
- -[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};
구조물의 마지막 세 멤버가 다른 이유와 고치는 방법은 무엇입니까?
미리 감사드립니다!
해결책
나는 당신의 문제의 근본이 3 바이트 값이라는 것입니다.
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#이 패딩 바이트를 삽입하면 나중에 값이 1 바이트를 끄는 데 유발합니다.
사용해 볼 수 있습니다
[StructLayout(LayoutKind.Sequential,Pack=1)]
구조물 정의 전에 가능한 최소 공간을 사용해야합니다.
C#의 마스터 링 스트러크 어떻게/왜 발생하는지에 대한 좋은 정보가 있습니다.
다른 팁
나는 그것을 의심한다 다니엘 l 그의 대답에서 올바른 길을 가고 있습니다.
깃발 다음에 4 번째 바이트를 추가하려고합니다. 내 생각에 C ++ 컴파일러가 단어 경계에서 값을 정렬하고 있다고 생각합니다. 그것은 C# 버전도 "정렬"할 것입니다.