TCP协议:TCP选项
简介
TCP头部的最后一个选项字段(options)是可变长的可选信息。这部分最多包含40字节,典型的TCP头部选项结构如图所示:
每个TCP报文头可以同时包含多个选项。每个TCP选项通常由Kind(选项类型)、Length(选项长度)和Data(选项数据)组成。
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      kind     |     Length    |       Data(可变长度)         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- 
    kind=0,选项表结束(EOP)选项 一个报文段仅用一次。放在末尾用于填充,用途是说明:首部已经没有更多的消息,应用数据在下一个32位字开始处 
- 
    kind=1,空操作(NOP)选项 没有特殊含义,一般用于将TCP选项的总长度填充为4字节的整数倍 
- 
    kind=2,最大报文段长度(MSS)选项 TCP连接初始化时,通信双方使用该选项来协商最大报文段长度。 TCP模块通常将MSS设置为(MTU-40)字节(减掉的这40字节包括20字节的TCP头部和20字节的IP头部)。这样携带TCP报文段的IP数据报的长度就不会超过MTU(假设TCP头部和IP头部都不包含选项字段,并且这也是一般情况),从而避免本机发生IP分片。对以太网而言,MSS值是1460(1500-40)字节。 
- 
    kind=3,窗口扩大因子选项 TCP连接初始化时,通信双方使用该选项来协商接收窗口的扩大因子。在TCP的头部中,接收窗口大小是用16位表示的,故最大为65535字节,但实际上TCP模块允许的接收窗口大小远不止这个数(为了提高TCP通信的吞吐量)。窗口扩大因子解决了这个问题。 假设TCP头部中的接收通告窗口大小是N,窗口扩大因子(移位数)是M,那么TCP报文段的实际接收通告窗口大小是N*2M,或者说N左移M位。注意,M的取值范围是0~14。 和MSS选项一样,窗口扩大因子选项只能出现在同步报文段中,否则将被忽略。但同步报文段本身不执行窗口扩大操作,即同步报文段头部的接收窗口大小就是该TCP报文段的实际接收窗口大小。当连接建立好之后,每个数据传输方向的窗口扩大因子就固定不变了。 
- 
    kind=4,选择性确认(Selective Acknowledgment,SACK)允许选项 TCP通信时,如果某个TCP报文段丢失,则TCP会重传最后被确认的TCP报文段后续的所有报文段,这样原先已经正确传输的TCP报文段也可能重复发送,从而降低了TCP性能。SACK技术正是为改善这种情况而产生的,它使TCP只重新发送丢失的TCP报文段,而不用发送所有未被确认的TCP报文段。 选择性确认允许选项用在连接初始化时,表示是否支持SACK技术。 
- 
    kind=5,SACK实际工作的选项 该选项的参数告诉发送方本端已经收到并缓存的不连续的数据块,从而让发送端可以据此检查并重发丢失的数据块。因为一个块信息占用8字节,所以TCP头部选项中实际上最多可以包含4个这样的不连续数据块(考虑选项类型和长度占用的2字节)。 
- 
    kind=8,时间戳选项 该选项提供了较为准确的计算通信双方之间的回路时间(Round Trip Time,RTT)的方法,从而为TCP流量控制提供重要信息。 
MSS
MSS选项用于协商TCP连接的最大报文段长度,避免IP报文分片。格式如下:
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       2       |     Length    |   Maximum Segment Size (MSS)  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
SACK
SACK特性是TCP的一个可选特性,是否启用需要收发双发进行协商,通信双发在SYN段或SYN+ACK段中添加SACK允许选项通知对端本端是否支持SACK,如果双发都支持,那么后续连接态通信过程中就可以使用SACK选项了。所以SACK允许选项只能出现在SYN段中。
+---------+---------+
| Kind=4  | Length=2|
+---------+---------+
连接建立后,接收方就可以通过SACK选项告诉发送方字节的实际接收情况。SACK选项格式如下:
0        1        2        3        4
                  +--------+--------+
       NOP        | Kind=5 | Length |
+--------+--------+--------+--------+
|      Left Edge of 1st Block       |
+--------+--------+--------+--------+
|      Right Edge of 1st Block      |
+--------+--------+--------+--------+
|                                   |
/            . . .                  /
|                                   |
+--------+--------+--------+--------+
|      Left Edge of nth Block       |
+--------+--------+--------+--------+
|      Right Edge of nth Block      |
由于整个TCP首部的选项部分不能超过40字节,所以一个ACK段中最多可以容纳4组SACK信息。
- Left Edge表示已收到的不连续块的第一个序号
- Right Edge表示已收到的不连续块的最后一个序号+1,即左闭右开区间。
通过ACK和SACK信息,发送方就可以确定接收方具体没有收到的数据就是从ACK到最大SACK信息之间的那些空洞的序号。