首页 > 代码库 > ipv4校验和计算
ipv4校验和计算
ipv4校验和的计算
原理:
计算方法一:除去校验和的两位,将其他的位相加:45+00+00+3c+55+81+00+00+40+01+ac+1c
0f+0d+ac+1c+0f+0e=
计算方法二:
校验和(checksum)算法,简单的说就是16位累加的反码运算:
计算函数如下:
我们在计算时是主机字节序,计算的结果封装成IP包时是网络字节序,注意这两者之间的区别,我们在从IP包里读取要转化为主机字节序,往IP包里存入时要转化为网络字节序在存入。
UINT32 Checksum(UINT32 cksum, VOID*pBuffer, UINT32 size)
{
INT8 num = 0;
UINT8 *p = (UINT8 *)pBuffer;
if ((NULL == pBuffer) || (0 == size))
{
return cksum;
}
while (size > 1)
{
cksum += ((UINT16)p[num] << 8 & 0xff00) | (UINT16)p[num + 1]& 0x00FF;
/*2个字节累加,先取网络字节序低位左移8位(变成主机字节序高位),与(加)上 网络字节序中的高位(主机字节序地位),即网络字节序要先变成主机字节序在进行累加,*/
size -= 2;
num += 2;
}
if (size > 0)
//如果长度为奇数
{
cksum += ((UINT16)p[num] << 8) & 0xFFFF;
//如果总的字节数为奇数,则最后一个字节单独相加
num += 1;
}
while (cksum >> 16)
{
cksum = (cksum & 0xFFFF) + (cksum >> 16);
//累加完毕将结果中高16位再加到低16位上,重复这一过程直到高16位为全0
}
return cksum;
}
注意:UINT32 cksum的类型,这里是4个字节的,防止在累加的过程中,数据溢出,(例如 0xFF 累加时就会内存溢出)
详细的计算过程和原理如下
一:ip 头 的计算:
直接对头部数据进行累加(不包括原来的checksum值):
1、ipv4包头
ipHeadLen =(pIpHeader->ver_ihl & 0x0F) << 2;
在ipv4 头中,版本类型和头长度加在一起是1 个字节(8位),各占4位,版本类型在前,长度在后,所以要取长度只能取低4 位,
pIpHeader->chksum = 0;
因为不包括原来的checksum值,所以在每次计算前先把checksum的值置0,然后计算
sum = Checksum(0, (VOID *)pIpHeader, ipHeadLen);
对整个ip包头的累加
pIpHeader->chksum = HTONS((UINT16)(~sum));
结果为计算值的反码,(别忘转化为网络字节序)
本文出自 “12034923” 博客,请务必保留此出处http://1406404036.blog.51cto.com/12034923/1887762
ipv4校验和计算