C# & C++ 校验和计算

C# & C++ checksum calculation

我需要你的帮助来计算 C# 中的校验和。下面的代码适用于用 C++ 编写的应用程序。应用程序正在从 UDP 接收数据包。这是接收和校验和计算的代码的一部分。

struct OPtoLSs {BlockReceivedS hdr; char data[0x100];}; //struct for received data
OPtoLSs mCKr;

#define hdrR mCKr.hdr.OPhdr
#define dataR mCKr.data

int const retHdr = recvfrom(sock, (char*)&hdrR, sizeof(hdrR), 0, (sockaddr*)(&from), &len);
int const retDat = recvfrom(sock, (char*)&dataR, hdrR.Length, 0, (sockaddr*)(&from), &len);
for(unsigned _int16 *p = (unsigned _int16*)&mCKr; p < (unsigned _int16*)&mCKr + ((retHdr+retDat)/2); p++)
{
   ChkSum=(_int16)((*p+ChkSum)&0xffff);
}
assert_hard(ChkSum==0xffff);

我需要在 C# 中正确计算校验和。我使用了下面的代码,但是当我从 C# 端向 C++ 端发送任何消息时,它会抛出此 error。请有人可以帮助在 C# 中进行此计算吗?感谢您的所有回复。

// mCKr.hdr.OPhdr equivalent
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Size = 12)]
 public struct OPpacketHdrS
 {
      public UInt32 packetMark;
      public UInt32 OPpacketID;       
      public UInt16 ChKSum
      {
          get
          {
              UInt16 accumulator = 0;
              unsafe
              {
                  fixed (OPpacketHdrS* x = &this)
                  {
                      for (UInt16* p = (UInt16*)x; p < x + 1; ++p)
                      {
                          accumulator += *p;
                      }
                  }
              }
              return accumulator;
          }
      }

      public UInt16 Length;    
}
// mCKr.data equivalent
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = 20)]
 public struct CommandKeyS
 {
      public OPpacketHdrS OPhdr;
      public mHdr Hdr; // Hdr.ID=CommandKeyR
      [MarshalAs(UnmanagedType.U2)]
      public UInt16 cmdKey, unused;
 }

服务器只对接收到的头和数据的一半计算校验和。发送的校验和应导致计算出的校验和变为 0xffff。 我假设您正在向服务器发送 CommandKeyS 结构并且它的大小是恒定的。我假设服务器上的 ChkSum 是 _int16 类型并初始化为 0。 我不知道 C#,所以用 C++ 代码替换了部分,希望它不会有太大的不同。您可以删除 ChKSum 字段的 get 函数,并在发送数据之前调用此函数来初始化校验和:

CalcChecksum( CommandKeyS* sentData )
{
  //At this point all fields in sentData, except of OPhdr.ChKSum are properly initialized.
  UInt16 accumulator = 0;

  unsafe
  {
    //Calculate checksum of the half of the data without using ChKSum.
    UInt32 chkSummedLen = sizeof( CommandKeyS )/2;
    UInt8* chkSummedEnd = ((UInt8*)sentData) + chkSummedLen;
    sentData->OPhdr.ChKSum = 0;
    for (UInt16* p = (UInt16*)sentData; p < chkSummedEnd; ++p)
    {
      accumulator += *p;
    }

    //Calculate ChKSum to make the calculated checksum be equal to 0xffff.
    sentData->OPhdr.ChKSum = 0xffff - accumulator;
  }
}

您的服务器使用的计算校验和的方法不明显而且可能不正确,因为数据的底部没有校验和。