一、传输层报文
1、TCP数据包的头
typedef struct _TCP_HEADER {
USHORT nSourPort ; // 源端口号16bit
USHORT nDestPort ; // 目的端口号16bit
UINT nSequNum ; // 序列号32bit
UINT nAcknowledgeNum ; // 确认号32bit
USHORT nHLenAndFlag ; // 前4位:TCP头长度;中6位:保留;后6位:标志位16bit
USHORT nWindowSize ; // 窗口大小16bit
USHORT nCheckSum ; // 检验和16bit
USHORT nrgentPointer ; // 紧急数据偏移量16bit
} TCP_HEADER, *PTCP_HEADER ;
2、UDP数据包的头
typedef struct _UDP_HEADER {
USHORT nSourPort ; // 源端口号16bit
USHORT nDestPort ; // 目的端口号16bit
USHORT nLength ; // 数据包长度16bit
USHORT nCheckSum ; // 校验和16bit
} UDP_HEADER, *PUDP_HEADER ;
进入协议栈的过程:(从协议栈出来刚好相反)
二、网络层报文
1、IP头
IP数据包也叫IP报文分组,传输在ISO网络7层结构中的网络层,它由IP报文头和IP报文用户数据组成,IP报文头的长度一般在20到60个字节之间,而一个IP分组的最大长度则不能超过65535个字节。
下图为IP分组的报文头格式,报文头的前20个字节是固定的,后面的可变。
//IP包
TIPHeader = packed record
iph_verlen: byte; // 版本和长度
iph_tos: byte; // 服务类型
iph_length: word; // 总长度,2个无符号字节所以只能65535
iph_id: word; // 标识
iph_offset: word; // 标志和片偏移
iph_ttl: byte; // 生存时间
iph_protocol: byte; // 协议
iph_xsum: word; // 头校验和
iph_src: longword; // 源地址
iph_dest: longword; // 目的地址
end;
这个结构体有什么用呢?其实在嗅探的时候就很有用了.
2、ICMP头和报文校验和的计算
//定义ICMP包头
typedef struct _ICMP_HEADER {
BYTE bType ; // 类型8bit
BYTE bCode ; // 代码8bit
USHORT nCheckSum ; // 校验和16bit
USHORT nId ; // 标识,本进程ID16bit
USHORT nSequence ; // 序列号16bit
UINT nTimeStamp ; // 可选项,这里为时间,用于计算时间32bit
} ICMP_HEADER, *PICMP_HEADER ;
发送ICMP报文时,必须由程序自己计算校验和,将它填入ICMP头部对应的域中。校验和的计算方法是:
将数据以字(16位)为单位累加到一个双字中(强转换双字类型),如果数据长度为奇数(奇数个字节),最后一个字节将被扩展到字,累加的结果是一个双字,最后将这个双字的高16位和低16位相加后取反,便得到了校验和!
// 计算ICMP包校验值
// 参数1:ICMP包缓冲区
// 参数2:ICMP包长度
USHORT GetCheckSum ( LPBYTE lpBuf, DWORD dwSize )
{
DWORD dwCheckSum = 0 ;
USHORT* lpWord = (USHORT*)lpBuf ;
// 累加
while ( dwSize > 1 )
{
dwCheckSum += *lpWord++ ;
dwSize -= 2 ;
}
// 如果长度是奇数
if ( dwSize == 1 )
dwCheckSum += *((LPBYTE)lpWord) ;
// 高16位和低16位相加
dwCheckSum = ( dwCheckSum >> 16 ) + ( dwCheckSum & 0xFFFF ) ;
// 取反
return (USHORT)(~dwCheckSum ) ;
}