前面用两节内容的篇幅介绍了TCP协议首部格式,TCP的基本功能都是靠其首部这些字段的支持。那么在固定首部之后,还有长度可变的选项字段,可以提供一些附加功能。既然是长度可变,说明选项肯定不止一个,这里面有些比较重要的,也是常用的选项,我们也有必要学习一下。
最大报文段长度(MSS)
MSS是TCP最初规定的一种选项,该字段的值规定了TCP报文数据部分的最大长度。这是一个值得注意的点,虽然它的名字是报文段长度,但实际上它是指去除了首部的数据部分的最大长度,我们是不是可以把它理解成是一种传输层TCP的"MTU值"呢。
从数据链路层的角度来看,我们知道以太网最初规定最小帧长的目的是:为了能在争用期时间之内检测到数据帧的是否发生碰撞的情况。如果是很短的帧,那么在检测碰撞的时候有可能就会发生问题。那如果我们从另一方面来看,如果是数据部分很短的帧,只有1个字节的数据,加上帧首部和帧尾部等开销,那么整体的网络利用率就不高,因为大部分的网络资源都用在传输开销上面。
类似的道理,传输层TCP要设置一个最大报文段长度也是为了解决网络利用率不高的问题。我们可以想一下这种情况:
如果在极端情况下,应用层传递下来的数据只有1个字节,传输层TCP要给它加上首部(最少20字节),到了网络层加上IP首部(最少20字节),到了数据链路层还要加上帧首部。这样来看的话,利用率就很低。相当于是用了一个大盒子里面装了一个小的瓜子。
所以从这个角度看,MSS应该设置的尽量大一些,尽量提高网络利用率。那么应该设置到什么样的程度呢?当然不能设置的太大,因为还要考虑到数据链路层规定了MTU值,如果在传输层把MSS设置的太大,那么整个的TCP报文就大,到了网络层之后这些都变成了IP包的数据部分,太大的数据部分通不过数据链路层的MTU,所以IP就要进行数据包的分片,分的片太多就有一定的安全隐患,因为只要接收端少收到其中一个片,整个的IP包就组装不成,无法向上层交付。
所以把MSS要设置为一个合适的大小,需要通信双方在TCP连接建立时进行确定,双方都把自己能够支持的MSS写入这一字段,以后就按照这个数值传送数据。但如果没有对这个值做出设置,那MSS就取默认值:536字节。
选择确认(SACK)
"选择确认"要和我们前面学习过的"连续ARQ的选择重传"联想起来,选择确认的意思是说:如果数据传输中,丢失了一些报文段,使得接收方接收的时候"缺少"中间的一些报文段,这时候接收方可以不把它们全部丢弃,而是可以先暂存下来,但是要告诉发送方丢失了哪些数据。这种"告诉"的方法就是使用选择确认。
我们前面学习确认号的时候,知道了确认号的意思是我期望接下来收到的数据序号,选择确认也是这样的。比如发送的是序号为1~4000的数据,但是接收方只收到了1~1000、1500~3000、3500~4000。那么接收方就要发送确认号为1001、3001、4001的选择确认,以便让发送方知道哪些数据是正常收到的。
如果使用选择确认,那么原来首部中的"确认号"字段用法仍然不变,只是增加了SACK选项。所以在建立TCP连接的时候,通信双方必须都约定好"允许SACK"。
用户超时(UTO)
"用户超时"选项用来设置TCP"超时定时器"的超时时间。前面在学习ARQ自动重传的时候,我们分析过,超时定时器的时间应该设置的比平均往返时间长一点是比较合理的。但这并不是固定的,TCP通信双方可以通过"用户超时"选项设置一个超时数值,并将设置的这个数值告诉对方。这个数值指出了:发送方愿意等待对方发来ACK的时间,也就是超时的时间。
窗口缩放(WSOPT)
在学习TCP报文首部格式的时候,我们知道了"窗口"的概念,窗口值指的是接收窗口的大小,实际上也就是接收缓存能够容纳对方发来多少数据。
那么,"窗口缩放"选项,顾名思义就是可以扩大接收窗口的大小,也可以将扩大后的窗口缩小回来。TCP首部"窗口值"字段长度是16位,也就意味着窗口最大是2^16大小,如果使用窗口缩放选项,则允许窗口可以扩大为2^30的大小。
当然,是否使用"窗口缩放"选项,由通信双方在TCP建立连接时进行协商,如果有一方使用了窗口扩大,当它不再需要扩大其窗口时,可以使窗口大小再回到2^16。
以上就是TCP首部中常用的几个选项,当然我们前面还学过一个"时间戳"的选项,具有防止序号绕回的功能,这也是一种选项。到这里,TCP首部就基本学完了(但是还没全部学完,"检验和"放到后面和UDP一起学习)。下一节我们学习TCP建立连接的过程。
参考教材:W.Richard Stevens《TCP/IP详解 卷一:协议》