IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法如下:
在发送数据时,为了计算数IP据报的校验和。应该按如下步骤:
(1)把IP数据报的首部都置为0,包括校验和字段。
(2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和。
(3)把得到的结果存入校验和字段中。
在接收数据时,计算数据报的校验和相对简单,按如下步骤:
(1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段。
(2)检查计算出的校验和的结果是否等于零。
(3)如果等于零,说明被整除,校验是和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。
这里的二进制反码求和让人有点不太明白,找了一个大多数协议栈实现的校验和计算代码:
unsigned short checksum(unsigned short *buf, int nword)
{
unsigned long sum = 0;
for(int i=0; i<nword; i++)
{
sum += *buf++;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short)~sum;
}
程序大概思路是:先求各个16bit字的和,然后把16bit字折半相加,最后再取反;但这跟二进制反码求和有什么关系?
用几个数试了一下,16bit字折半相加就是模2^16-1,然后再取反,跟先取反再求和的结果是一样的,又想到以前看到
过1的补码,2的补码,到
在发送数据时,为了计算数IP据报的校验和。应该按如下步骤:
(1)把IP数据报的首部都置为0,包括校验和字段。
(2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和。
(3)把得到的结果存入校验和字段中。
在接收数据时,计算数据报的校验和相对简单,按如下步骤:
(1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段。
(2)检查计算出的校验和的结果是否等于零。
(3)如果等于零,说明被整除,校验是和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。
这里的二进制反码求和让人有点不太明白,找了一个大多数协议栈实现的校验和计算代码:
unsigned short checksum(unsigned short *buf, int nword)
{
unsigned long sum = 0;
for(int i=0; i<nword; i++)
{
sum += *buf++;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short)~sum;
}
程序大概思路是:先求各个16bit字的和,然后把16bit字折半相加,最后再取反;但这跟二进制反码求和有什么关系?
用几个数试了一下,16bit字折半相加就是模2^16-1,然后再取反,跟先取反再求和的结果是一样的,又想到以前看到
过1的补码,2的补码,到