TCP协议的一些总结(二)
六、 名词说明
1. 最大报文段长度MSS
最大报文段长度(MSS)表示TCP传往另一端的最大块数据的长度。当一个连接建立时,连接的双方都要通告各自的MSS。
MSS让主机限制另一端发送数据报的长度。加上主机也能控制它发送数据报的长度,这将使以较小MTU连接到一个网络上的主机避免分段。
MSS只是表示TCP数据和选项的长度和,整个IP包的长度还要加上IP和TCP首部的长度。
MSS如果没有限制,当然是越大越好,这样传输率会比较高,比如,MSS为256,加上IP和TCP首部,一共296个字节,传输率为256/296=84.5%;而如果MSS为1024,则传输率为1024/1064=96.2%。
图:MSS和MTU
最终TCP传输的数据段长度由MTU和对方的MSS决定,如上图,sun传输的数据段长度为256,而slip传输的数据段长度为512(552-40)
2. 2MSL等待状态
MSL是指报文段最大生存时间Maximum Segment Lifetime)。TIME_WAIT状态之所以需要等待2MSL时间,可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)。而且,可以防止上一个使用该地址和端口的连接的迟到数据被新的连接接收到。
在连接处于TIME_WAIT状态时,会将接收到的迟到的数据都丢掉,而且该连接所使用的端口不能被其他连接使用。如果非要使用相同的端口,就需要设置TCP的SO_REUSEADDR了。
3. 平静时间
指出TCP在重启动后的MSL秒内不能建立任何连接。这就称为平静时间(quiet time)。
如果处于2MSL等待端口的主机出现故障,它会在MSL秒内重新启动,并立即使用该端口则会造成问题,平静时间就是为了防止这种情况的。但实际上大多数主机的启动时间都大于MSL。
4. 连接请求等待队列
TCP在底层维护了一个队列,这个队列可以在应用层由于忙碌而无法快速的处理TCP连接的情况下,将一定数目的连接放到该队列中,在放入队列前,会完成TCP的3次连接握手(即建立好连接)。而当队列已满的情况下再有新的连接请求时,则会直接拒绝。
该连接等待队列将TCP底层作为输入,而应用层作为输出。
图:等待队列
5. Nagle算法
TCP交互式输入可以很好的说明TCP传输数据的交互流程:
图:一种可能的处理远程交互按键回显的方法
上图可以看出,TCP的每个数据传输都会有对应的一个ACK报文,不管方向是什么样的。
如果网络上都是这种小的数据报,很容易造成网络的拥堵。通常TCP在接收到数据时并不立即发送ACK;相反,它推迟发送,以便将ACK与需要沿该方向发送的数据一起发送(有时称这种现象为数据捎带ACK)。
图:经受时延的确认
上图中可以看出,每个回显的数据都需要有一段延时才能返回确认数据报,这个确认数据报就称为经受时延的确认。原因很简单,确认报在等待一个同方向的数据报一起传输,但等待了一个时间段(200ms的整数倍)之后会被强制发送。这个200ms不是指接收到数据报到返回确认的时间间隔,而是两个确认报之间的时间间隔。
Nagle算法减轻微小数据包对网络造成的压力,减少网络拥塞的可能。这种拥塞在局域网上不会出现,但在广域网上会有很大的影响。
该算法要求一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组的确认到达之前不能发送其他的小分组。相反,TCP收集这些少量的分组,并在确认到来时以一个分组的方式发出去。该算法的优越之处在于它是自适应的:确认到达得越快,数据也就发送得越快。而在希望减少微小分组数目的低速广域网上,则会发送更少的分组。
图:Nagle算法下的数据传输
上图第14和15个数据包并没违反Nagle算法原则,第14个数据包是对第12个数据包的响应,在响应的同时,又收到了第13个数据包,而第15个数据包正好响应第13个数据包。
6. 滑动窗口
图:滑动窗口
图:窗口边沿的移动
几点总结:
1) 发送方不必发送一个全窗口大小的数据。
2) 来自接收方的一个报文段确认数据并把窗口向右边滑动。这是因为窗口的大小是相对于确认序号的。
3) 窗口的大小可以减小,但是窗口的右边沿却不能够向左移动。
4) 接收方在发送一个ACK前不必等待窗口被填满。
7. 窗口大小通告
上图中的第9个报文通告自己的窗口大小为4095而非4096,说明在tcp缓冲区中有一个字节没有被应用层读出,而第11个数据包的窗口大小为4094,说明缓冲区中又增加了一个未被应用层处理的字节,达到了2个字节。
8. 慢启动
慢启动(slow start)算法通过观察到新分组进入网络的速率应该与另一端返回确认的速率相同而进行工作。慢启动为发送方的TCP增加了另一个窗口:拥塞窗口(congestion window),记为cwnd。当与另一个网络的主机建立TCP连接时,拥塞窗口被初始化为1个报文段(即另一端通告的报文段大小)。每收到一个ACK,拥塞窗口就增加一个报文段(cwnd以字节为单位,但是慢启动以报文段大小为单位进行增加)。发送方取拥塞窗口与通告窗口中的最小值作为发送上限。拥塞窗口是发送方使用的流量控制,而通告窗口则是接收方使用的流量控制。
发送方开始时发送一个报文段,然后等待ACK。当收到该ACK时,拥塞窗口从1增加为2,即可以发送两个报文段。当收到这两个报文段的ACK时,拥塞窗口就增加为4。这是一种指数增加的关系。
图:慢启动及拥塞窗口变化
9. 吞吐量
通常发送一个分组的时间取决于两个因素:传播时延(由光的有限速率、传输设备的等待时间等引起)和一个取决于媒体速率(即媒体每秒可传输的比特数)的发送时延。对于一个给定的两个接点之间的通路,传播时延一般是固定的,而发送时延则取决于分组的大小。在速率较慢的情况下发送时延起主要作用,而在千兆比特速率下传播时延则占主要地位。
发送时延:发送时延=数据/带宽
传播时延:传播时延=发送距离/传播速率
通过下面的两个图可以看出数据传输和ACK的传输过程,time0~time8表示了一个数据包发送的这个过程,这个time8就是往返时间RTT。
图:时间0~15的成块数据吞吐量举例
图:时间16~31的成块数据吞吐量举例
10. 带宽时延乘积
可以计算通道的容量为:
capacity(bit) = bandwidth(b/s) ×round-trip time (s)
一般称之为带宽时延乘积。
不论是带宽还是时延均会影响发送方和接收方之间通路的容量。
图:RTT(左)与带宽(右)增倍造成通道容量增倍
11. 拥塞
当数据到达一个大的管道(如一个快速局域网)并向一个较小的管道(如一个较慢的广域网)发送时便会发生拥塞。当多个输入流到达一个路由器,而路由器的输出流小于这些输入流的总和时也会发生拥塞。
图:从较大管道向较小管道发送分组引起的拥塞
在该图中,我们已经标记路由器R1为“瓶颈”,因为它是拥塞发生的地方。
12. TCP的坚持定时器
上图中,如果第9个报文丢失,发送端不知道接收端的通告窗口变为非0,则继续等待,而接收端已经告诉发送端通告窗口变化从而进入等待报文接收状态,那么两端都会进入无限的等待之中。
为防止这种死锁情况的发生,发送方使用一个坚持定时器(persist timer)来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送方发出的报文段称为窗口探查( window probe )。
一个例子:
图:坚持定时器的例子
当发送端接收到通告窗口为0的ACK后,会引起发送端启动坚持定时器,然后经过了4.9494秒后发送了一个窗口探查请求,收到一个通过窗口为0 的ACK,然后重新计时。
坚持定时器采用了普通的TCP指数退避,即间隔依次为1.5、3、6、12、24、48和60秒。
糊涂窗口综合症:
基于窗口的流量控制方案,如TCP所使用的,会导致一种被称为“糊涂窗口综合症SWS(Silly Window Syndrome)”的状况。如果发生这种情况,则少量的数据将通过连接进行交换,而不是满长度的报文段。
可以在任何一端采取措施避免出现糊涂窗口综合症的现象。
1) 接收方不通告小窗口。通常的算法是接收方不通告一个比当前窗口大的窗口(可以为0),除非窗口可以增加一个报文段大小(也就是将要接收的MSS)或者可以增加接收方缓存空间的一半,不论实际有多少。
2) 发送方避免出现糊涂窗口综合症的措施是只有以下条件之一满足时才发送数据:(a)可以发送一个满长度的报文段;(b)可以发送至少是接收方通告窗口大小一半的报文段;(c)可以发送任何数据并且不希望接收ACK(也就是说,我们没有还未被确认的数据)或者该连接上不能使用Nagle算法。
13. TCP的保活定时器
不使用保活定时器的理由:(1) 在出现短暂差错的情况下,这可能会使一个非常好的连接释放掉;(2)它们耗费不必要的带宽;(3)在按分组计费的情况下会在互联网上花掉更多的钱。
客户主机必须处于以下4个状态之一:
1) 客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常工作的。服务器在两小时以后将保活定时器复位。如果在两个小时定时器到时间之前有应用程序的通信量通过此连接,则定时器在交换数据后的未来2小时再复位。
2) 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务器将不能够收到对探查的响应,并在75秒后超时。服务器总共发送10个这样的探查,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。
3) 客户主机崩溃并已经重新启动。这时服务器将收到一个对其保活探查的响应,但是这个响应是一个复位,使得服务器终止这个连接。
4) 客户主机正常运行,但是从服务器不可达。这与状态2相同,因为TCP不能够区分状态4与状态2之间的区别,它所能发现的就是没有收到探查的响应。
七、 意外情况
1. 建立连接超时
客户端发起连接请求,发送SYN请求,如果在一定时间内没有得到对应的ACK,则会进行重新请求,间隔时间逐渐增长的。
2. 同时打开
图:同时打开
3. 同时关闭
图:同时关闭
4. 造成FIN_WAIT_2状态
当主动关闭端接收到FIN的ACK报文后,一直没有接收到对端发送的FIN请求,则会使当前连接始终处于FIN_WAIT_2状态,而对端(被动)则会长时间处于CLOSE_WAIT状态。
5. ICMP差错
TCP能够遇到的最常见的ICMP差错就是源站抑制、主机不可达和网络不可达。
TCP忽略ICMP主机不可达的差错并坚持重传,直到达到一定门限值时,TCP会返回连接超时错误。
一个接收到的主机不可达或网络不可达实际上都被忽略,因为这两个差错都被认为是短暂现象。这有可能是由于中间路由器被关闭而导致选路协议要花费数分钟才能稳定到另一个替换路由。在这个过程中就可能发生这两个ICMP差错中的一个,但是连接并不必被关闭。