IPv4版本的头部信息比较复杂,含有校验等信息,但是也导致路由器需要进行计算,增加了延时,IPv6中取消了对应的校验和。
这个图很好的显示了Ipv4的IP包内的组成,可以看出头部总长度是20字节。
然后我们看下Ipv4和Ipv6版本的IP头部的区别:
直接说下重点吧,就是关于IP头部的计算问题:
这是我随手抓的一个包,就以它为例进行计算:
IP的所有字段:
4500 0042 3038 0000 4011 6257 c0a8 0afa af90 [6ce9]
全部相加: 29314 => 然后把溢出的第一位移动到最后一位 得到 9316
得到二进制后人后取反:
1001 0011 0001 0110
0110 1100 1110 1001 => 6CE9(正解)
二进制反码求和,即为先进行二进制求和,然后对和取反。
下面是最常用的C语言的校验算法,虽然Linux内核使用更高效的汇编写成的,但是这个C语言版本的在其他位置更常用。
-
/*求校验和函数*/
-
USHORT CheckSum(USHORT *buffer, int size)
-
{
-
unsigned long cksum=0;
-
while (size > 1)
-
{
-
cksum += *buffer++;
-
size -= sizeof(USHORT);
-
}
-
if (size)
-
{
-
cksum += *(UCHAR*)buffer;
-
}
-
/*对每个16bit进行二进制反码求和*/
-
cksum = (cksum >> 16) + (cksum & 0xffff);
-
cksum += (cksum >>16);
-
return (USHORT)(~cksum);
-
}
阅读(865) | 评论(0) | 转发(0) |