目前碰到一个socket连接大量卡在close_wait状态的问题。
经过百度,bing查找资料分析。
用netstat查看连接的状态,发现有的连接状态在sync_recv状态,有的连接在close_wait。
然后新的连接一直都无法建立。
1.初步怀疑是连接一直不释放,导致fd不够用。
但是通过到进程下的proc/进程号/fd目录下去查看当前open的fd个数,以及ulimt -a查看允许open的最大fd个数,结合status中的峰值fd个数。
发现是fd资源是够用的。因此排除这一可能。
2.由于连接已经建立不了,所以怀疑是线程资源不够,导致的读写事件无法有效的得到处理,也无法及时去调用closesocket。
目前正在复现核实。
closesocket默认so_linger都是0的,所以是强制关闭句柄,但是后台发送未发送的数据。
但是关于close_wait状态做了测试,并得到一下几点结论:
1.在主动进行关闭连接的一端,如果closesocket,则会主动发送FIN包,FIN包表示这一方向上的数据不会再有的了。然后主动发起的这一端开始等待对方的ACK和FIN包,进行状态的两次迁移。
2.被动收到的FIN包的这一被动关闭连接的一端,先会回一个AcK表示准备去断开连接的。然后如果当前有数据还在缓冲区里的,会将缓冲区里的数据处理完,然后再发FIN包,表示数据已处理完。这里的FIN包,显然是需要调动closesocket来主动关闭的,shutdown调动没试过,不瞎说。
3.上述步骤2中,如果读buffer中有数据,迟迟不处理,且不调用closesocket则有可能会导致无法发送fin包,状态会一直维持在CLOSE_WAIT状态,直至超时,发送RST?连接快速tear down。
4.如果读buffer中有数据,即使不处理,不读取,只要调用closesocket,仍然可以迅速的发送FIN包断开连接。
5.但是shutdown是用于优雅关闭的,即如果关闭时有未发送的数据,则先发送完再发FIN包关闭,若有没有接收处理完的则向对端发送RST包重建连接,接收完后。
closesocket是否是优雅关闭,需要看so_linger的设置,若l_linger设置为非0,则作为限制其在该时间段内发送或者接收处理完的期限,否则强制关闭;l_onoff为0,则表示是优雅关闭,非零才有可能是强制关闭。(未验证)
另:关于优雅关闭和强制关闭socket,可以参考下:
http://blog.csdn.net/user_920/article/details/7779311