在TCP中有四种计时器:重传计时器、持续计时器、保活计时器和TIME-WAIT计时器
重传计时器
在拥塞控制中有提到RTO——重传计时器。重传计时器是对发送出去的数据进行重传计时,如果在计时器超时后没有收到返回的ACK确认,发送端就会重新发送队列中重传报文。一般俩讲,使用RTO重传计时器有如下规则:
- 当TCP发送了位于发送队列最前端的报文段后就启动这个RTO计时器
- 如果队列为空则停止计时器,否则重启计时器
- 当计时器超时后,TCP会重传发送队列最前端的报文段
- 当一个或者多个报文段被累计确认后,这个或者这些报文段会被清除出队列
重传计时器保证了接收端能够接收到丢失的报文段,继而保证了接收端交付给接收进程的数据始终的有序完整的。因为接收端永远不会把一个失序不完整的报文段交付给接收进程。
持续计时器
持续计时器是为了解决因为零窗口值而导致的死锁问题的。当接收端的rwnd的值是0的时候,发送端收到后便不再发送数据,直到接收到接收端窗口不为零的确认报文。但是即使接收端发送了一个非零的确认,但这个确认仍然可能丢失。需要注意的是这个确认是没有重传机制的,所以只要接收端发送了这个非零确认报文后便完成了任务,即认为对方已经收到了该非零确认。于是接收端等待发送端发送数据,而由于确认报文的丢失,发送端一直在等待接收端发送非零确认。这样双方都在等待对方的响应,于是就发生了死锁问题。持续计时器就是为了纠正这个问题而设置的计时器。当发送端收到rwnd=0的报文后,便启动一个持续计时器,如果这个计时器超时后还没有收到接收端的非零确认报文就会向接收端发送一个探测报文,这个探测报文只有一字节的数据,而且有一个序号,但是这个序号不需要接收端进行确认(TCP中对这个序号的处理原则是始终不需要确认),这个探测报文仅仅是让接收端重传一个非零确认。接收端收到这个探测报文后会重传一个非零确认。持续计时器的超时时间是重传时间的值,如果计时器超时没有收到接收端的响应则发送端会发送另一个探测报文,并将计时器的超时时间加倍,计时器重新计时。如果仍然没有收到接收端的响应则继续加倍并重新计时,直到超时时间到达一个上限(一般为60秒),之后每次隔60秒发送一个探测报文,直到窗口被重新打开。
保活计时器
所谓保活就是不让客户端与服务端的连接一直空闲着,比如有一条连接,发送端发送完一些数据后就没有然后了,那么这条连接一直被占用着,导致不必要的开销。为了解决这个问题,当接收端收到数据后会启动一个保活计时器,如果两个小时都没有继续收到发送端发送的数据,接收端会连续发送10个探测报文(每隔75秒发一个),如果还没有收到发送端发送的数据,接收端假定客户端遇到了故障,于是关闭这条连接。
TIME-WAIT计时器
也叫2MSL(2倍最长报文生存时间)计时器,实是在TCP终止连接启动的计时器。当主动关闭的一方收到被动关闭一方FIN=1的控制报文信息后状态由FIN-WAIT-2变为TIME-WAIT,并发送一个ACK确认报文,同时启动计时器开始计时,如果被动关闭的一方在2MSL后没有发送重传请求主动关闭的一方即认为对方已经收到ACK报文并关闭了连接,于是主动关闭的一方才把连接关闭。设置这个计时器的主目的是为了能够正常关闭服务端的连接!