TCP数据被封装在一个IP数据报中,TCP首部在数据报中的位置跟UDP首部一样,紧跟在IP首部后面。为简单起见,我们先看不计任何选项的TCP首部,它总共20字节,下面是其定义:
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
defines"
#endif
__u16 window;
__u16 check;
__u16 urg_ptr;
};
下面我们依次介绍每个字段的含义。
source和dst分别表示源和目的端口号,每个TCP段都包含源端口号和目的端口号,用于寻找发送端和接收端的应用进程,这两个值加上IP首部中的源端IP地址和目的端IP地址就可以唯一确定一个TCP连接。
seq是发送端序列号,用于标识从TCP发送端向接收端发送的数据字节流,也就是说,每发送一个字节,该字段值加1,为了安全起见,它的初始值是一个随机
生成的数,它到达32位最大值后,又从零开始。ack_seq是确认序列号,发送给对端,用于确认希望对端发送的下一个数据报的起始序号,显然,一个
TCP客户端发起连接请求时,ack_seq的值为0。
doff占4位,表示首部长度,它的单位并非字节,而是32bit,所以,一个不含任何选项的TCP首部,其首部长度是5(5*4=20字节),含有选项时,还要加上选项的长度。res1为保留位,cwr, ece用途暂时不明。
window是16位滑动窗口的大小,单位为字节,起始于确认序列号字段指明的值,这个值是接收端正期望接收的字节数,其最大值是63353字节。
check是检验和,覆盖了整个的TCP报文段,这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证。
urg_ptr是一个紧急指针,是一个正的偏移量,和序列号字段中的值相加表示紧急数据最后一个字节的序列号。
urg, ack, psh, rst, syn, fin为6个标志位,它们的含义如下:
urg: 紧急指针有效。
ack: 确认序号有效。
psh: 接收方应该尽快将这个报文段交给应用层。
rst: 重建连接。
syn: 同步序号,用来发起一个连接。
fin: 发送端完成发送任务。
内核源代码在函数mytcp_transmit_skb中建立tcp首部。
阅读(157) | 评论(0) | 转发(0) |