tcp报文段首部结构基础知识
- tcp报文段首部结构
2. 源码中的结构体
/usr/include/netinet/tcp.h(为方便,仅选取一种情况,其他情况请在源码中看)
typedef u_int32_t tcp_seq;
struct tcphdr
{
u_int16_t th_sport; /* source port */
u_int16_t th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
# if __BYTE_ORDER == __LITTLE_ENDIAN
u_int8_t th_x2:4; /* (unused) */
u_int8_t th_off:4; /* data offset */
# endif
# if __BYTE_ORDER == __BIG_ENDIAN
u_int8_t th_off:4; /* data offset */
u_int8_t th_x2:4; /* (unused) */
# endif
u_int8_t th_flags;
# define TH_FIN 0x01
# define TH_SYN 0x02
# define TH_RST 0x04
# define TH_PUSH 0x08
# define TH_ACK 0x10
# define TH_URG 0x20
u_int16_t th_win; /* window */
u_int16_t th_sum; /* checksum */
u_int16_t th_urp; /* urgent pointer */
};
- tcp首部分为20字节的固定长度首部,和长度可变的选项部分首部。固定长度首部分为5行,每行4字节。首部总体有多长,由固定首部第四行里面的首部长度字段
th_off:4
决定(表示有多少个32字节,所以也可以叫首部行数字段。which is
the offset of the first byte of data in 32-bit words)。 - 第一行的
th_sport
和th_dport
是源端口号和目的端口号。端口是运输层与应用层的服务接口。运输层的复用和分用功能都要通过端口才能实现。 - 第二行和第三行是本次发送的序号字段
th_seq
和确认号字段th_ack
。序号字段——占 4 字节。TCP 连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节在整个报文字节流中的序号(用来解决网络包乱序(reordering)问题。)。确认号字段——占 4 字节,是期望收到对方的下一个报文段的数据的第一个字节的序号(用于确认收到,用来解决不丢包的问题。)。 - 第四行第一个16位是4位首部长度和6位标志符,中间是6位保留字段。首部长度——占 4 bit,它指示意32bit为单位的TCP首部长度。(最多16行,64字节;固定5行,20字节。叫做data offset是因为data的第一个字节前面都是首部且offset从0开始,首部行数和data offset相等)。六个标志位,依次是:
- 紧急比特 URG —— 当 URG =1 时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送。(一般不使用)
- 确认比特 ACK —— 只有当 ACK =1 时确认号字段才有效。当 ACK = 0 时,确认号无效。
- 推送比特 PSH (PuSH) —— 接收 TCP** 收到推送比特置 1 的报文段,就尽快地交付给接收应用进程,而不再等到整个缓存都填满了后再向上交付**。
- 复位比特 RST (ReSeT) —— 当 RST = 1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
- 同步比特 SYN —— 同步比特 SYN 置为 1,就表示这是一个连接请求或连接接受报文。
- 终止比特 FIN (FINal) —— 用来释放一个连接。当FIN=1 时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
关于这几个bit什么时候会被设置,详见:TCP头部解析
第五行的第2个16位是窗口字段 —— 占 2 字节。窗口字段用来控制对方发送的数据量,单位为字节。TCP 连接的一端根据设置的缓存空间大小确定自己的接收窗口大小,然后通知对方以确定对方的发送窗口的上限。(2^16B=2^6MB=64MB。1s传完,对应网络中的:2^9Mb/s的速度)。也就是著名的滑动窗口(SlidingWindow),用于流量控制。
6. 第五行
第五行分为两个16位的校验和字段和紧急指针字段
- 检验和 —— 占 2 字节。检验和字段检验的范围包括首部和数据这两部分。
- 紧急指针字段 —— 占 16 bit。紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。
A better term is the urgent offset, since this field is a 16-bit unsigned offset that must be added to the sequence number field (th_seq) togive the 32-bit sequence number of the last byte of urgent data.
- 可选项
- MSS:TCP 只规定了一种选项,即最大报文段长度 MSS (Maximum Segment Size)。MSS 告诉对方 TCP:“我的缓存所能接收的报文段的数据字段(不包括首部)的最大长度是 MSS 个字节。