標籤:計算方法 網路 return 主機
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校正和計算