我正在编写一个简单的程序来发送和接收icmp消息。 我编写了以下内容来计算icmp消息的校验和:
char sbuf[] = " This is a test message..";
sbuf[0] = 0x10;
sbuf[1] = 0x00;
sbuf[2] = 0x00;
sbuf[3] = 0x00;
sbuf[4] = 0x00;
sbuf[5] = 0x00;
sbuf[6] = 0x00;
sbuf[7] = 0x00;
for (int i = 0; i < sizeof(sbuf); i += 2)
checksum += (sbuf[i] << 8) + sbuf[i + 1];
if (sizeof(sbuf) % 2)
checksum += sbuf[sizeof(sbuf) - 1] << 8;
checksum = (checksum >> 16) + (checksum & 0xffff);
checksum = ~(checksum + (checksum >> 16));
sbuf[2] = checksum >> 8;
sbuf[3] = checksum & 0x00ff;
问题是,当messege长度为奇数时,计算的校验和不正确。
checksum += sbuf[sizeof(sbuf) - 1] << 8;
部分有问题,但我无法弄清楚是什么
我该如何解决这个问题?
由于
答案 0 :(得分:0)
所以我想我找到了解决方案。
for (int i = 0; i < sizeof(sbuf) - 1; i += 2)
checksum += (sbuf[i] << 8) + sbuf[i + 1];
if (sizeof(sbuf) % 2)
checksum += sbuf[sizeof(sbuf) - 1];
现在这确实为任何长度的messege计算了正确的校验和。但我无法确认它是否是一个真正的解决方案,或者只是因为我的消息的最后一个字节始终为零。
答案 1 :(得分:0)
您可能喜欢我的版本
uint16_t Checksum(const void* data, size_t len) {
auto p = reinterpret_cast<const uint16_t*>(data);
uint32_t sum = 0;
if (len & 1) {
// len is odd
sum = reinterpret_cast<const uint8_t*>(p)[len - 1];
}
len /= 2;
while (len--) {
sum += *p++;
if (sum & 0xffff0000) {
sum = (sum >> 16) + (sum & 0xffff);
}
}
return static_cast<uint16_t>(~sum);
}
std::cout << "0x" << std::hex << std::setw(4)
<< Checksum(sbuf, sizeof(sbuf))
<< std::endl;