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;
}
}
您的服务器使用的计算校验和的方法不明显而且可能不正确,因为数据的底部没有校验和。
我需要你的帮助来计算 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;
}
}
您的服务器使用的计算校验和的方法不明显而且可能不正确,因为数据的底部没有校验和。