1、persist timer:当接收方建议的窗口大小为0时,发送方就会停止发送,直到接收方有缓存空间时再用一个窗口值非零的ACK提示发送方可以继续发送。但是这个称为window update的ACK报文段很可能会发生丢失,这个时候就不可避免地发送了死锁。因此,发送方需要设置一个persist timer,每隔一段时间就向接收方发送一个询问报文window probes,当接收方可以接收数据时就重新开始发送
2、通常发送方都会包含一个字节数据的报文段作为window probes,该字节的数据其实就是它真实要发送的下一个字节数据。并且与重传不同的是,window probes会一直进行下去,不会超过一定次数就停止重传
3、Silly Window Syndrome:为了避免大量的小数据包在网络上传输,通常接收方会等到缓冲已经满足一定大小时才重新将advertised window置为非零。如上图所示,第8个报文段其实是一个window probe,我们从接收方返回的ack来看,这个探测报文中的一个数据字节其实是被接受的,但是返回的建议窗口大小仍然为0,这时其实就是在避免小的建议窗口的出现。至于为什么最后一个ack报文段中建议的窗口大小只有509这么小呢?其实是因为之前已经建议了一个1533的窗口大小,发送方其实只发送了1024个字节的数据,如果这里突然将其变为0,那么发送方的窗口的右侧就可能向左移动(会导致已发送的数据变到窗口外去了),这是不允许的。
4、Keepalive timer:当我们在客户端和服务端建立一条TCP连接之后,如果两者直接不发送数据,那么不论过多久,不管连接中间路由器崩溃了多少次,只要两端的主机不重启,那么连接依旧是建立的。但是这会带来一些问题,例如很多客户机与同一台服务器之间建立了连接,并且这些客户机都被切断电源了,这时服务器不知道客户机都已经崩溃了,所以依然建立着连接,这样其实造成了资源的极大的浪费。因此keepalive timer就是一个定时询问机制,从而判断对方主机是否已经崩溃。
5、对于keepalive timer的设置一直有反对的声音,只要原因在于它们的存在可能导致原本良好的连接因为中间网络一些暂时的问题而导致连接关闭,不过即使是这样,大多数实现仍然保留了keepalive timer
6、通常,如果server与client之间超过两个小时没有活动,那么server就会向client发送一个探测,这时可能遇到以下四种情况:
1)client正常运行,这时server就会得到相应的返回报文,并且重置keepalive timer
2)client已经崩溃了,这样server就收不到返回报文了,于是server会每隔75s重发一次探测,发满十次后断开连接
3)client崩溃之后又重启了,这时server会得到返回报文要求reset,于是server会断开连接
4)最后,client依然在运行,但是网络不可达了,这时的结果和2)其实是相同的
一般来说,keepalive探测报的发送对应用程序是透明的,只有在2,3,4三种情况出现时,TCP才会告诉它