您好,登錄后才能下訂單哦!
ipv4校驗(yàn)和的計(jì)算
原理:
計(jì)算方法一:除去校驗(yàn)和的兩位,將其他的位相加:45+00+00+3c+55+81+00+00+40+01+ac+1c
0f+0d+ac+1c+0f+0e=
計(jì)算方法二:
校驗(yàn)和(checksum)算法,簡單的說就是16位累加的反碼運(yùn)算:
計(jì)算函數(shù)如下:
我們在計(jì)算時(shí)是主機(jī)字節(jié)序,計(jì)算的結(jié)果封裝成IP包時(shí)是網(wǎng)絡(luò)字節(jié)序,注意這兩者之間的區(qū)別,我們在從IP包里讀取要轉(zhuǎn)化為主機(jī)字節(jié)序,往IP包里存入時(shí)要轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序在存入。
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個(gè)字節(jié)累加,先取網(wǎng)絡(luò)字節(jié)序低位左移8位(變成主機(jī)字節(jié)序高位),與(加)上 網(wǎng)絡(luò)字節(jié)序中的高位(主機(jī)字節(jié)序地位),即網(wǎng)絡(luò)字節(jié)序要先變成主機(jī)字節(jié)序在進(jìn)行累加,*/
size -= 2;
num += 2;
}
if (size > 0)
//如果長度為奇數(shù)
{
cksum += ((UINT16)p[num] << 8) & 0xFFFF;
//如果總的字節(jié)數(shù)為奇數(shù),則最后一個(gè)字節(jié)單獨(dú)相加
num += 1;
}
while (cksum >> 16)
{
cksum = (cksum & 0xFFFF) + (cksum >> 16);
//累加完畢將結(jié)果中高16位再加到低16位上,重復(fù)這一過程直到高16位為全0
}
return cksum;
}
注意:UINT32 cksum的類型,這里是4個(gè)字節(jié)的,防止在累加的過程中,數(shù)據(jù)溢出,(例如 0xFF 累加時(shí)就會(huì)內(nèi)存溢出)
詳細(xì)的計(jì)算過程和原理如下
一:ip 頭 的計(jì)算:
直接對頭部數(shù)據(jù)進(jìn)行累加(不包括原來的checksum值):
1、ipv4包頭
ipHeadLen =(pIpHeader->ver_ihl & 0x0F) << 2;
在ipv4 頭中,版本類型和頭長度加在一起是1 個(gè)字節(jié)(8位),各占4位,版本類型在前,長度在后,所以要取長度只能取低4 位,
pIpHeader->chksum = 0;
因?yàn)椴话ㄔ瓉淼腸hecksum值,所以在每次計(jì)算前先把checksum的值置0,然后計(jì)算
sum = Checksum(0, (VOID *)pIpHeader, ipHeadLen);
對整個(gè)ip包頭的累加
pIpHeader->chksum = HTONS((UINT16)(~sum));
結(jié)果為計(jì)算值的反碼,(別忘轉(zhuǎn)化為網(wǎng)絡(luò)字節(jié)序)
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。