tcp关闭状态详解
tcp关闭连接不区分客户端和服务端,哪一端口可以主动发起关闭连接请求。所以为了描述方便,描述中的“主动方”表示主动发起关闭连接一方,“被动方”表示被动关闭连接一方。
1. tcp关闭连接状态转换
上图是tcp连接主动关闭端的状态转换图:
(1)应用层调用close函数发起关闭连接请求
(2)发送FIN到对端,关闭写通道,自己进入FIN_WAIT1状态
(3)等待对端的确认ACK到来,接受到ACK后进入FIN_WAIT2状态;如果在超时时间内没有收到确认ACK直接进入CLOSED状态
(4)如果在FIN_WAIT1状态时收到了对端的FIN则进入CLOSING状态(双发都发出了关闭连接请求)
(5)在FIN_WAIT2接受到了对端FIN后进入TIME_WAIT状态;如果在超时时间内没有收这个FIN则直接进入CLOSED状态
(6)在TIME_WAIT状态等待2个MSL(2个报文最长存活周期)后进入CLOSED状态
上图是tcp连接被动关闭方的状态转换图
(1)收到对端FIN后,关闭读通道进入CLOSE_WAIT状态
(2)在CLOSE_WAIT状态等待应用层调用close函数关闭连接
(3)如果在超时时间内调用了close,则进入LAST_ACK状态;否则直接进入CLOSED状态
(4)在LAST_ACK状态,发送FIN到对端并等待对端的确认ACK
(5)如果在超时时间内收到了确认ACK则进入CLOSED状态,否则直接进入CLOSED状态
2. 状态分析
2.1 FIN_WAIT1
这个状态在实际的工作中很少见。主动方调用close函数关闭连接后立刻进入FIN_WAIT1状态,此时只要收到对端确认ACK后马上会进入FIN_WAIT2状态。因为对端确认ACK是TCP协议栈自己控制的,所以很快就会发出。出现场景:主动方等待ACK过程中网络断掉了,导致长时间收不到ACK,主动方就会停留在CLOSE_WAIT1状态上(超时时间:一般默认60s超时)。此时我们可以使用netstat -anpt 命令看到这种状态。
NOTE:这个状态如果超时,将直接进入CLOSED状态。关于超时时间你可能需要了解:tcp_fin_timeout这个配置参数。
2.2 FIN_WAIT2
这个状态比较常见。主动端在等待对端FIN到来过程中,会一你直保持这个状态(超时时间:一般默认是60s)。由于网络中断,或者对端很忙还没来得及发送FIN、或者对端有bug忘记关闭连接等都会导致主动端长时间处于FIN_WAIT2状态。如果主动方发现大量FIN_WAIT2状态时,应该引起相关人员的注意,这可能是网络不稳、对端程序bug的表现。
NOTE:这个状态如果超时,将直接进入CLOSED状态。关于超时时间你可能需要了解:tcp_fin_timeout这个配置参数。
2.3 TIME_WAIT
这个状态最常见。主动方收到对端的FIN后进入TIME_WAIT状态。然后发送最后一个确认ACK到对端。之后等待2个最大的报文存活周期,正常的关闭流程客户端TCP连接都会经过这个状态,最终进入CLOSED状态。所以我们使用netstat -anpt命令发现客户端有很多的TIME_WAIT,一般这是正常的现象。
NOTE:
* 这个状态的连接还没有真正关闭,所以占用的文件句柄和端口号等资源也没有释放。如果TIME_WAIT状态的连接过多,将会导致文件句柄或者端口号等资源不足。如果你想控制这个状态连接的数量,你可能需要详细了解:tcp_max_tw_buckets tcp_tw_recycle tcp_tw_reuse三个系统配置。
* 对于有大量短链接服务的服务器来说,服务端主动关闭连接会产生大量的TIME_WAIT,如果不及时回收这些个连接会造成资源严重浪费。不过一个应用层系统都有自己最大并发连接数限制、操作系统也有最大TIME_WAIT连接数限制。所以一般也不会产生大的问题。
* 等待2MSL的原因:
(1)保证残留网络报不会被新连接接收而产生数据错乱。由于自己上一次发送的数据包可能还残留在网络中,等待2MSL时间可以保证所有残留的网络报在自己关闭前都已经超时。
(2)确保自己最后ACK发到对端。因为ACK发送也可能会失败,这是对端会重新发送FIN,如果已经CLOSED了那么对端将收到RST而不是ACK了,这不符合TCP可靠关闭策略。
2.4 CLOSING
双发几乎同时都调用了close接口主动关闭连接,此时都进入了FIN_WAIT1状态。如果在FIN_WAIT1状态期望收到对方的ACK但却收到了对方的FIN,这时候双方都进入CLOSING状态。然后都给对方一个ACK确认,收到了ACK后就会进入CLOSED状态了。
NOTE:这个状态如果超时,将直接进入CLOSED状态。关于这个超时时间的设置我暂时还没有找到?
2.5 CLOSE_WAIT(重点说明下这个状态)
这个状态表明TCP连接等待被关闭。只可能在被动方出现。如果被动方存在大量的CLOSE_WAIT状态需要因为我们的特别注意了。我们要仔细研究确认为什么被动方迟迟不愿关闭连接(或许是我们程序中的bug开启了连接,用完后却忘记关闭)
目前开发过程中遇到如下这个场景导致被动方有很多的CLOSE_WAIT状态:
A是一个应用程序,B是一个tomcat服务器
A开了一个连接Conn,发送请求给B
A接受相应数据后没有调用Conn.close关闭连接,在A端垃圾回收这些Conn对象前,这些连接一直保持着
B端的连接超时后会主动发起关闭连接请求给A,此时A进入了CLOSE_WAIT状态,B进入了FIN_WAIT2状态,由于A迟迟不发送FIN给B,B端触发timeout直接进入了CLOSED状态。
这样一个场景B端由于有超时设置一个为60s,不会存在大量的FIN_WAIT2状态
但是A端就会残留大量的CLOSE_WAIT状态(CLOSE_WAIT状态也有超时,但是太大,默认为43200s,详情见tcp_timeout_close_wait系统配置)。还好A端的java虚拟机的最大对内存配置较小,由于CLOSE_WAIT状态连接同样占用了内存资源,数量很多后就会触发垃圾回收,此时A端的CLOSE_WAIT的连接Conn对象就会被销毁了(同时内存和句柄、端口等资源也被释放了)
很明显这是一个bug导致的问题,如果没有及时回收的话,就会把内存、句柄或者端口等资源给用完,导致程序crash掉。
2.6 LAST_ACK
这个状态只可能在被动端出现。当被动端调用close接口关闭连接后便会进入这个状态,同时发送一个FIN给对端。在接受对端的ACK确认后便会进入CLOSED状态,这个状态一般不易出现,除非网络中断,一般对端会很快给与响应的。
2.7 状态总结
主动端可能出现的状态:FIN_WAIT1、FIN_WAIT2、CLOSING、TIME_WAIT
被动端可能出现的状态:CLOSE_WAIT LAST_ACK
叙述中提到的超时时间在我的另一片文章tcp连接超时那点事中有具体的分析
NOTE:
(1)主动端出现大量的FIN_WAIT1时需要注意网络是否畅通、出现大量的FIN_WAIT2需要仔细检查程序为何迟迟收不到对端的FIN(可能是主动方或者被动方的bug)、出现大量的TIME_WAIT需要注意系统的并发量/socket句柄资源/内存使用/端口号资源等。
(2)被动端出现大量的 CLOSE_WAIT 需要仔细检查为何自己迟迟不愿调用close关闭连接(可能是bug,socket打开用完没有关闭)
tcp关闭状态详解的更多相关文章
- TCP连接状态详解
tcp状态: LISTEN:侦听来自远方的TCP端口的连接请求 SYN-SENT:再发送连接请求后等待匹配的连接请求 SYN-RECEIVED:再收到和发送一个连接请求后等待对方对连接请求的确认 ES ...
- TCP连接状态详解及TIME_WAIT过多的解决方法
上图对排除和定位网络或系统故障时大有帮助,但是怎样牢牢地将这张图刻在脑中呢?那么你就一定要对这张图的每一个状态,及转换的过程有深刻地认识,不能只停留在一知半解之中.下面对这张图的11种状态详细解释一下 ...
- TCP/IP状态详解[转]
TCP正常建立和关闭的状态变化 TCP连接的建立可以简单的称为三次握手,而连接的中止则可以叫做 四次握手. 建立连接 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建 ...
- TCP/IP状态详解
今天犯懒了,本来自己也做了一些相应的笔记,但是发现这篇写的更好一些,简单易懂,而且有图有真相,为了方便以后查看,在此转载了,在此基础上加了自己的笔记 TCP正常建立和关 ...
- MySQL关闭过程详解和安全关闭MySQL的方法
MySQL关闭过程详解和安全关闭MySQL的方法 www.hongkevip.com 时间: -- : 阅读: 整理: 红客VIP 分享到: 红客VIP(http://www.hongkevip.co ...
- 用netstat查看网络状态详解
--用netstat查看网络状态详解 -----------------------------2014/06/11 一.Linux服务器上11种网络连接状态: ...
- 【转载】TCP /IP协议详解
首先,TCP/IP不是一个协议,而是一个协议族的统称. 里面包括了IP协议,IMCP协议,TCP协议,以及http.ftp.pop3协议等等. TCP/IP协议分层 提到协议分层,我们很容易联想到IS ...
- TCP /IP协议详解【转】
转自:https://www.jianshu.com/p/0cf648510bce?utm_campaign=maleskine&utm_content=note&utm_medium ...
- (转)iOS应用程序生命周期(前后台切换,应用的各种状态)详解
原文:http://blog.csdn.net/totogo2010/article/details/8048652 iOS应用程序生命周期(前后台切换,应用的各种状态)详解 分类: ...
随机推荐
- JPA-04
一.JPQL JPA的查询语言(和SQL非常像,面向对象的查询语言) 有list集合可以用size看长度 分页:setFirstResult().setMaxResults(); 获取总条数:getS ...
- jasperreports实现pdf文档的生成
1.导入jar包(pom.xml构建) <dependencies> <dependency> <groupId>com.lowagie</groupId&g ...
- Breathe me
Help, I have done it again 帮帮我,我又做错了. I have been here many times before 哪怕这已经不是一两次了. Hurt myself ag ...
- ELK从5.6.3升级到6.3.0总结
ELK从5.6.3升级到6.3.0总结 由于6.3.0默认有es的监控功能,并且我们现在es总是有各种问题,原有的es开源插件head和HQ的监控都不够详细,所以决定升级es集群.我们目前es有5个n ...
- Jupyter-NoteBook-你应该知道的N个小技巧
智能决策上手系列教程索引 不断更新部分内容来自于翻译整理 多行输出 在Notebook的中开头cell中添加以下代码可以实现多行输出: from IPython.core.interactiveshe ...
- 虚拟机找不到/mnt/hgfs挂载目录——debian与 vmware
如果在安装好 VMware Tools 并在设置里面设定好共享目录之后仍然找不到 /mnt/hgfs 默认挂载目录,那么尝试以下步骤: 1. 确认VMware Tools 和共享目录设定已经完成: 2 ...
- How To Setup a CA
How To Setup a CA Original Version by Ian AldermanUpdated by Zach Miller Introduction You can set up ...
- ASP.NET MVC项目实现BasePage基类用作ASPX.CS网页继承
在ASP.NET MVC项目开发,还是需要创建一些Web Page来实现一些功能,如呈现报表等... 但是一旦项目的.ASPX网页太多了,其中的程序代码也会有代码冗余,出现这些情况,我们得需要对这些代 ...
- Javascript高级编程学习笔记(72)—— 模拟事件(2)IE事件模拟
IE中的事件模拟 低版本的IE浏览器作为前端开发的一股清流,想避过都不行 虽然低版本IE正在逐步被市场淘汰,不得不承认IE8以下的浏览器依然占了不小的份额 所以这里大概介绍IE8以下的低版本IE中的事 ...
- 13.缓存、三级缓存、内存溢出、AsyncTask
SharePreference工具类 /** * SharePreference封装 * */ public class PrefUtils { public static final String ...