聲明:歡迎任何人和組織轉載本blog中文章,但必須標記文章原始連結和作者資訊。
本文連結:http://blog.csdn.net/li_007/archive/2010/06/02/5642818.aspx
開拓進取的小烏龜------->CSDN點滴點點滴滴Blog
首先根據IP協議定義IP資料包頭(關於IP協議頭各部分的定義,具體參考http://en.wikipedia.org/wiki/IPv4),注意嚴格的類型大小,不然資料轉換會出現錯誤。
/* // http://en.wikipedia.org/wiki/IPv4<br />-|------------->16<--------------|------------->16<--------------|<br />-|0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7|<br />-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br /> | vesion| IHL | TypeOfService | TotleLength |<br />-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br /> | identification |flags| FragmentOffset |<br />-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br /> | Time to Live | Protocol | Header Checksum |<br />-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br /> | Source Address |<br />-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br /> | Destination Address |<br />-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br /> | Options | Padding |<br />-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br />*/<br />typedef struct _iphdr // 定義ip協議頭的資料結構,具體參考ip包的包頭協議。<br />{<br />unsigned char headAndVersionLength;// 4位首部長度+4位IP版本號碼<br />unsigned char tos; // 8位服務類型TOS<br />unsigned short totalLength; // 16位總長度(位元組)<br />unsigned short ident; // 16位標識<br />unsigned short flagsAndFramOset; // 3位標誌位和13位分段位移位<br />unsigned char ttl; // 8位存留時間 TTL<br />unsigned char protocol; // 8位協議(TCP,UDP或者其他協議)<br />unsigned short checkedSum; // 16位IP首部效驗和<br />unsigned int sourceAddr; // 32位源IP地址<br />unsigned int destAddr; // 32位目標IP地址<br />}ipHeader;<br />int parseIPPackage(char * buf, int bufferSize)<br /> {<br /> if(NULL == buf)<br /> return 0;<br /> ipHeader * pIpHeader = (ipHeader *)buf;<br /> int headerLength = 0;<br /> int ipVersion = 0;<br /> char tos = '0';<br /> unsigned short totalLength = 0;<br /> unsigned short identification = 0;<br /> unsigned short flags = 0;<br /> unsigned short framOset = 0;<br /> unsigned short ttl = 0;<br /> unsigned short protocol = 0;<br /> unsigned short checkedSum = 0;<br /> char srcAddr[MAX_ADDR_LEN] = {0};<br /> char destAddr[MAX_ADDR_LEN] = {0};<br /> SOCKADDR_IN saSrc, saDest;</p><p> // 擷取源IP地址<br /> saSrc.sin_addr.S_un.S_addr = pIpHeader->sourceAddr;<br /> strncpy_s(srcAddr, MAX_ADDR_LEN, inet_ntoa(saSrc.sin_addr), MAX_ADDR_LEN);<br /> // 擷取目標IP地址<br /> saDest.sin_addr.S_un.S_addr = pIpHeader->destAddr;<br /> strncpy_s(destAddr, MAX_ADDR_LEN, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);<br /> // 計算IP包頭長度<br /> headerLength = sizeof(unsigned long) * (pIpHeader->headAndVersionLength & 0xf);<br /> ipVersion = (pIpHeader->headAndVersionLength >> 4);<br /> tos = pIpHeader->tos;<br /> totalLength = pIpHeader->totalLength;<br /> identification = pIpHeader->ident;<br /> flags = pIpHeader->flagsAndFramOset >> 13;<br /> framOset = pIpHeader->flagsAndFramOset & 0x1fff;<br /> ttl = pIpHeader->ttl;<br /> protocol = pIpHeader->protocol;<br /> checkedSum = pIpHeader->checkedSum;<br /> return 1;<br /> }
首先來看一個調試記憶體,在這裡都是以16進位來表示。
在這裡我們需要注意在記憶體中字元儲存方式(其實是由於CPU的決定的),也就是大小端和記憶體對齊原則。關於大小端做一個簡單的解釋。DEC和Intel的機器CPU一般採用小端. IBM, Motorola和Sun的機器CPU一般採用大端. 當然這並不能代表所有情況. 有的CPU即能工作於小端, 又能工作於大端, 比如ARM, PowerPC, Alpha. 具體情形參考處理器開發手冊。
更形象的表述樣本,來看看我在網上找到的圖形。 比如一個int x, 起始地址為0x100, 它的值為0x1234567. 則它所佔據的記憶體為0x100, 0x101, 0x102和0x103這4個位元組,地址具體數值組織如:
Ok,可以結合大小端樣本圖與調試記憶體樣本圖,仔細分析分析,計算IP資料包頭的各個變數的具體數值。然後結合IP資料包頭定義來理解這個IP資料包的含義。