`

Tcp主动关闭连接导致TIME_WAIT状态

阅读更多

          最近写了一个进程,需要通过20个线程循环600个用户获取每一个用户的xx信息,是通过socket连接oracle mdb服务器获取的,但是在本机windows上测试发现大量的TIME_WAIT状态,按照网上的说法,调了注册表的参数,但是无济于事,Socket.setReuseAddress方法也是没有效果,最后放弃了,在测试环境的unix上也是一样,但是没有去调节测试环境的参数,最后直接上了生产,生产上的参数应该是设置过的,最后复习了下这个经典的TIME_WAIT状态状态

          tcp建立连接需要3个握手,但是关闭连接需要4个握手,关闭连接后主动关闭的一方会处于time_wait状态一段时间,这个是可以设置的,好像windows最少是30s,这个time_wait状态的目的大概有两个

1。防止上一次连接中的包,迷路后重新出现,影响新连接

(经过2MSL,上一次连接中所有的重复包都会消失)
2。可靠的关闭TCP连接
在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发
fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以
主动方要处于 TIME_WAIT 状态,而不能是 CLOSED

 

         这是tcp关闭连接的client/server直接的数据交互过程

        

 

 

还有一种close_wait

在客户端主动关闭时,服务器端也要被动关闭(服务器端也要主动调用closesocket),如果服务器端不被动关闭,客户端就收不到服务器端发来 的FIN,就一直在FIN_WAIT_2了,而此时服务器端只收到客户端发来的FIN(自己只向客户端发了ACK,没有向客户端发FIN),也一直停留在 CLOSE_WAIT

 出现大量close_wait的现象,主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。代码需要判断socket,一旦读到0,断开连接,read返回负,检查一下errno,如果不是AGAIN,就断开连接。

解决方法
基本的思想就是要检测出对方已经关闭的socket,然后关闭它。

可以参考tomcat server 源码如何检测client 关闭了socket,server端的socket可以循环的read,一旦出现timeout异常就可以关闭了

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics