TCP 报文段的首部格式
TCP 虽然是面向字节流的,但其传送的数据单元却是报文段。一个TCP报文段分为首部和数据两部分,而 TCP 的全部功能的体现在它首部
中各字段的作用。 因此,弄清 TCP 报文段首部各字段的作用对掌握 TCP 的工作原理非常重要。TCP 报文段的首部格式如下图所示(由首部固定的 20 个字节+后面 4n 字节选择性添加选项组成):
首部固定部分各字段的意义(20字节)
源端口和目的端口
:各占两个字节,分别写如源端口号和目的端口号。目的端口号是为了接收方需要交付报文,源端口号是为了接收接收方的返回信息。序号
:占 4 个字节。是指报文段中第一个字节的编号。(TCP 连接中传送的字节流中的每一个字节都按顺序编号。)确认号(ACKs)
:占 4 个字节。是指期望收到对方
下一个报文段的第一个数据字节的序号。注意:若确认号 = N,则表面:到序号 N-1 为止的所有数据都已正确收到。
下图举个说明序号和确认号字段意义的例子
确认 ACK
:仅当 ACK = 1 时确认号字段才有效。当 ACK = 0 时,确认号无效。TCP 建立连接后所有的报文段都必须把 ACK 置为 1。同步 SYN
:在连接建立时用来同步序号。SYN 置为 1 表示这是一个连接请求或连接接收报文。当 SYN = 1 而 ACK = 0 时,表明这是一个连接请求报文段。对方若同意建立连接的话,那对应的响应报文段中有 SYN= 1 和 ACK = 1.终止 FIN
:用来释放一个连接。当 FIN = 1 时,表面该报文段的发送方的数据已经发送完毕,并要求释放运输连接。窗口
:占 2 个字节。指发送本报文段的一方的接收窗口。表示接收方目前允许发送对方的数据量(以字节为单位,窗口值是[0,2^16-1])。之所以要有这个限制,是因为接收方的数据缓存空间有限,用于处理 TCP 流量控制。检验和
:占 2 字节。检验和字段检验的范围包括首部和数据这两个部分。
TCP 的流量控制
流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。接收方是有缓存的,缓存中有空闲的空间,也有已接收到的数据,要使得发送方传的数据不让这个缓存容器溢出即为流量控制。下图是接收方缓存数据的结构和走向:
流量控制的实现原理
利用滑动窗口去实现流量控制。接收方在建立连接的时候会将返给发送方报文段首部窗口值赋值(接收方缓存支持量),窗口值会随着接收方缓存的可用空间而发生改变。当给发送方发送 0 窗口的时候,发送方停止发送,等待接收方的非零窗口通知。 下图是滑动窗口实现流量控制的例子:
死锁问题
引入死锁:
当接收方发送给发送方零窗口报文段后不久,接收方中缓存有了一些存储空间,给发送方发送报文段的时候,报文段在传送过程丢失了,接收方和发送方之间失去了联系,如果没有其他措施,这种一直延续的互相等待即为死锁。
解决方案:
TCP 为每一个连接设有一个持续计时器。TCP 连接的一方收到对方的零窗口通知的时候就开启持续计时器。若计时器时间到,就发送一个零窗口探测报文段, 而对方在确认到这个探测报文段时就给出当时的窗口值。如果窗口值仍然为 0 ,那继续设置持续计时器,如果不为 0 ,死锁问题即可解决。