【问题标题】:C# & C++ checksum calculationC# & C++ 校验和计算
【发布时间】:2021-05-08 12:55:16
【问题描述】:

我需要你的帮助来计算 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,那么校验和的价值是多少? (assert_hard(ChkSum==0xffff);)
  • 如果我理解你的问题是正确的..然后在调试输出中我得到 36750..并且每个发送的 msg 这个数字都会增加一个
  • 您的代码通过检查 (assert_hard(ChkSum==0xffff); 要求校验和值为 0xffff。真正的价值似乎不同,你得到了这个断言。您确定发送的数据必须具有 0xffff 校验和吗?调试时,发送和接收的校验和的值是多少?
  • 错误弹出是因为它的校验和不是 0xffff,而大多数时候它不能是 0xffff。所以......我再次问:这个 assert_hard 是必需的吗?
  • 要明确,这不是 C# 代码的错。应该是C++代码的问题。它可能会被错过,因为它大部分时间都在发布模式下运行。

标签: c# c++ struct checksum


【解决方案1】:

服务器只计算接收到的一半头部和数据的校验和。发送的校验和应该导致计算的校验和变为 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;
  }
}

你的服务器计算校验和的方式并不明显,也可能不正确,因为数据的底部没有校验和。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 2015-01-02
    相关资源
    最近更新 更多