理解tcp关闭连接中的time_wait状态

首先看一下tcp关闭连接时的四次握手过程:


1.Client向Server发送FIN包,表示Client主动要关闭连接,然后进入FIN_WAIT_1状态,等待Server返回ACK包。此后Client不能再向Server发送数据,但能读取数据。

2.Server收到FIN包后向Client发送ACK包,然后进入CLOSE_WAIT状态,此后Server不能再读取数据,但可以继续向Client发送数据。

3.Client收到Server返回的ACK包后进入FIN_WAIT_2状态,等待Server发送FIN包。
4.Server完成数据的发送后,将FIN包发送给Client,然后进入LAST_ACK状态,等待Client返回ACK包,此后Server既不能读取数据,也不能发送数据。
5.Client收到FIN包后向Server发送ACK包,然后进入TIME_WAIT状态,接着等待足够长的时间(2MSL)以确保Server接收到ACK包,最后回到CLOSED状态,释放网络资源。

6.Server收到Client返回的ACK包后便回到CLOSED状态,释放网络资源。


但是有些爬虫服务器或者WEB服务器为什么有时候会有大量TIME_WAIT状态出现?

从 上面的示意图可以看得出来,TIME_WAIT是主动关闭连接的一方保持的状态,在发完最后一个ack状态后,发起者的状态会调整为TIME_WAIT。 对于爬虫服务器来说他本身就是“客户端”,在完成一个爬取任务之后,他就 会发起主动关闭连接,从而进入TIME_WAIT的状态,然后在保持这个状态2MSL(max segment lifetime  /proc/sys/net/ipv4/tcp_fin_timeout)时间之后,彻底关闭回收资源。2MSL一般是大于30s,小于4分钟. 最小也要30s,再大就没啥意义了.  为什么要这么做?明明就已经主动关闭连接了为啥还要保持资源一段时间呢?这个是TCP/IP的设计者规定 的,主要出于以下两个方面的考虑:

1. 收到ack,但是迷路回包的情况: 防止上一次连接中的包,迷路后重新出现,影响干扰新连接(经过2MSL,上一次连接中所有的重复包都会消失)

2. ack丢失的情况: 在主动关闭方发送的最后一个 ack(fin) ,有可能丢失。这时候对方(被动方)会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。另外这么设计TIME_WAIT 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。

如果接收到rst,也就是tcp连接重置,服务端应用有报错。 

reset报文发送场景:

RST的标志位,这个标识为在如下几种情况下会被设置。

1.当尝试和未开放的服务器端口建立tcp连接时,服务器tcp将会直接向客户端发送reset报文
2.双方之前已经正常建立了通信通道,也可能进行过了交互,当某一方在交互的过程中发生了异常,如崩溃等,异常的一方会向对端发送reset报文,通知对方将连接关闭
3.当收到TCP报文,但是发现该报文不是已建立的TCP连接列表可处理的,则其直接向对端发送reset报文
4.ack报文丢失,并且超出一定的重传次数或时间后,会主动向对端发送reset报文释放该TCP连接

另外我们做大量api请求时会遇到下面的问题. Broken pipe和Connection reset by peer  .   这其实也是reset的报错一种.

发布了8 篇原创文章 · 获赞 28 · 访问量 14万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览