سؤال

لدي عميل 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#.

هذه هي المشكلة:

آخر 3 أعضاء في tPacket_5000_E هم Int32 (لقد جربت UInt32 أيضًا)، وهو DWORD في C++.القيم قبل هؤلاء الأعضاء الثلاثة، وهي لا 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# لديه بعض المعلومات الجيدة حول كيفية/لماذا يحدث هذا.

نصائح أخرى

وأظن أن دانيال ل هو على الطريق الصحيح في إجابته.

سأحاول إضافة البايت الرابع بعد العلم.أعتقد أن مترجم C++ الخاص بك يقوم بمحاذاة القيم على حدود الكلمات.سيؤدي ذلك إلى "محاذاة" إصدار C# أيضًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top