IP数据包包头分析

 

声明:欢迎任何人和组织转载本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 -|------------->16<--------------|------------->16<--------------| -|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| -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | vesion| IHL | TypeOfService | TotleLength | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | identification |flags| FragmentOffset | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct _iphdr // 定义ip协议头的数据结构,具体参考ip包的包头协议。 { unsigned char headAndVersionLength;// 4位首部长度+4位IP版本号 unsigned char tos; // 8位服务类型TOS unsigned short totalLength; // 16位总长度(字节) unsigned short ident; // 16位标识 unsigned short flagsAndFramOset; // 3位标志位和13位分段偏移位 unsigned char ttl; // 8位生存时间 TTL unsigned char protocol; // 8位协议(TCP,UDP或者其他协议) unsigned short checkedSum; // 16位IP首部效验和 unsigned int sourceAddr; // 32位源IP地址 unsigned int destAddr; // 32位目标IP地址 }ipHeader; int parseIPPackage(char * buf, int bufferSize) { if(NULL == buf) return 0; ipHeader * pIpHeader = (ipHeader *)buf; int headerLength = 0; int ipVersion = 0; char tos = '0'; unsigned short totalLength = 0; unsigned short identification = 0; unsigned short flags = 0; unsigned short framOset = 0; unsigned short ttl = 0; unsigned short protocol = 0; unsigned short checkedSum = 0; char srcAddr[MAX_ADDR_LEN] = {0}; char destAddr[MAX_ADDR_LEN] = {0}; SOCKADDR_IN saSrc, saDest; // 获取源IP地址 saSrc.sin_addr.S_un.S_addr = pIpHeader->sourceAddr; strncpy_s(srcAddr, MAX_ADDR_LEN, inet_ntoa(saSrc.sin_addr), MAX_ADDR_LEN); // 获取目标IP地址 saDest.sin_addr.S_un.S_addr = pIpHeader->destAddr; strncpy_s(destAddr, MAX_ADDR_LEN, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN); // 计算IP包头长度 headerLength = sizeof(unsigned long) * (pIpHeader->headAndVersionLength & 0xf); ipVersion = (pIpHeader->headAndVersionLength >> 4); tos = pIpHeader->tos; totalLength = pIpHeader->totalLength; identification = pIpHeader->ident; flags = pIpHeader->flagsAndFramOset >> 13; framOset = pIpHeader->flagsAndFramOset & 0x1fff; ttl = pIpHeader->ttl; protocol = pIpHeader->protocol; checkedSum = pIpHeader->checkedSum; return 1; }

 

首先来看一个调试内存截图,在这里都是以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数据包的含义。

 

 

 

你可能感兴趣的:(C++)