11.4.5 定位TCP报头的编程方法
TCP的数据结构如图11.13所示。
图11.13 TCP数据结构示意图
对应的数据结构在头文件<Linux/tcp.h>中定义,代码如下:
struct tcphdr
{
__u16 source; /*源地址端口*/
__u16 dest; /*目的地址端口*/
__u32 seq; /*序列号*/
__u32 ack_seq; /*确认序列号*/
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u16 res1:4, /*保留*/
doff:4, /*偏移*/
fin:1, /*关闭连接标志*/
syn:1, /*请求连接标志*/
rst:1, /*重置连接标志*/
psh:1, /*接收方尽快将数据放到应用层标志*/
ack:1, /*确认序号标志*/
urg:1, /*紧急指针标志*/
ece:1, /*拥塞标志位*/
cwr:1; /*拥塞标志位*/
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4, /*偏移*/
res1:4, /*保留*/
cwr:1, /*拥塞标志位*/
ece:1, /*拥塞标志位*/
urg:1, /*紧急指针标志*/
ack:1, /*确认序号标志*/
psh:1, /*接收方尽快将数据放到应用层标志*/
rst:1, /*重置连接标志*/
syn:1, /*请求连接标志*/
fin:1; /*关闭连接标志*/
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
__u16 window; /*滑动窗口大小*/
__u16 check; /*校验和*/
__u16 urg_ptr; /*紧急字段指针*/
};
对于TCP协议,其IP头部的protocol的值应该为6,通过计算IP头部的长度可以得到TCP头部的地址,即TCP的头部为IP头部偏移ihl*4。TCP的源端口和目的端口可以通过成员source和dest来获得。下面的代码将源端口和目的端口的值打印出来:
//*打印TCP报文的源端口值和目的端口值*/
if(p_iphdr->protocol==6)
{
/*取得TCP报头*/
struct tcphdr*p_tcphdr = (struct tcphdr*)(p_iphdr+p_iphdr->ihl*4);
/*打印源端口值*/
printf("src port:%d/n", ntohs(p_tcphdr->source));
/*打印目的端口值*/
printf("dest port:%d/n", ntohs(p_tcphdr->dest));