原理
P/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,采用的都是将数据流视为16位整数流进行重复叠加计算。为了计算检验和,首先把检验和字段置为0。然后,对有效数据范围内中每个16位进行二进制反码求和,结果存在检验和字段中,如果数据长度为奇数则补一字节0。当收到数据后,同样对有效数据范围中每个16位数进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全0或全1(具体看实现了,本质一样; 校验时可能返回~checksum) 。如果结果不是全0或全1,那么表示数据错误。
例子:
- #include <stdio.h>
-
- unsigned short checksum(unsigned short *pdate, int size)
- {
- unsigned int sum=0;
- while (size>1)
- {
- sum += *pdate;
- pdate++;
- size -= sizeof(short);
- }
-
- if (size)
- sum += *(unsigned char*)pdate;
-
- while(sum>>16)
- {
- sum = (sum & 0xffff) + (sum>>16);
- }
-
- return ~sum;
- }
-
- int main(void)
- {
- unsigned short checksum_code=0;
- unsigned short date[] = {0,0x4500, 0x0029, 0x44f1,0x4000, 0x8006, 0xc0a8, 0x01ae, 0x4a7d, 0x477d};
- unsigned short check_res=0;
-
- checksum_code = checksum((unsigned short*)date, sizeof(date));
- date[0] = checksum_code;
- printf("generate:%x\n", checksum_code);
-
- check_res= checksum((unsigned short*)date, sizeof(date));
- printf("check result:%x\n", check_res);
- return 0;
- }
编译运行:
