c 套接字编程中的time_wait close_wait解决

在进行服务器维护的时候,发现后台有大量进程处于TIME_WAIT状态。

如:netstat -antp

tcp        0      0 10.1.10.147:52759           10.1.10.147:10086           TIME_WAIT  

而此时客户端在连接服务器的时候,出现很卡的现象。重启服务器程序(不重启机器)后,卡顿现象消失,TIME_WAIT状态的程序消失。在网络上查询后,得知TIME_WAIT会占用系统套接口资源,导致客户端在连接服务器的时候,套接字不够用。

那么什么是TIME_WAIT状态?

time_wait状态是指套接字编程中,主动调用close关闭连接一方所处的状态。与TIME_wai类似的还有以下几种状态:

TIME_WAIT     主动调用close一方的状态

CLOSE_WAIT 被动关闭一方的状态,相对于主动调用close方。

FIN_WAIT_1 执行close时,己方发送结束信号的状态

FIN_WAIT_2 被动方同意主动方关闭的状态


一个典型的TCP连接终止可以用图描述如下: 

client                                               server 

                                           fin M
close FIN_WAIT_1 ----------------->close_wait (被动关闭)            

                               ack m+1           
FIN_WAIT_2       <-----------------read 返回0

                                           fin n
TIME_WAIT        <----------------- close

                             ACK N+1 
                           -----------------> closed

首先客户端调用close(发送fin m信号,并处于fin_wait_1状态),因此客户端最后会处于TIME_WAIT状态。

此时服务器端会接收到数据,此时调用read读取数据,read会返回0.表示对方已经执行了关闭操作。此时服务器端可以调用close,向客户端发送fin n信号。

在编程上,客户端调用close以后的所有工作就归操作系统管理了,此时客户端的操作系统会向服务器发送ack n+1的确认信号,让服务器可以完整的关闭整个连接。这样整个连接就正常的关闭了。但此时客户端依然会处于time_wait状态,因为难免最后的ack n+1信号会丢失,需要重发。


以上讲述了客户端先调用close的情形,在实际情况下,服务器端也会由于客户端崩溃或其他机制主动执行close。此时服务器端也会存在一些进程处于TIME_WAIT状态。服务器上如果TIME_WAIT进程较多,就会影响服务器的性能。因为套接字也是一种系统资源,这种资源总是有限的。此时就需要调整系统参数来降低time_wait的进程数(如果是错误的编程的话,请先修改代码错误)。

方法vim /etc/sysctl.conf

#对于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃,不应该大于255,默认值是5,对应于180秒左右时间   
net.ipv4.tcp_syn_retries=2  
#net.ipv4.tcp_synack_retries=2  
#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为300秒  
net.ipv4.tcp_keepalive_time=1200  
net.ipv4.tcp_orphan_retries=3  
#表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间  
net.ipv4.tcp_fin_timeout=30    
#表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。  
net.ipv4.tcp_max_syn_backlog = 4096  
#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭  
net.ipv4.tcp_syncookies = 1  
  
#表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭  
net.ipv4.tcp_tw_reuse = 1  
#表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭  
net.ipv4.tcp_tw_recycle = 1  
  
##减少超时前的探测次数   
net.ipv4.tcp_keepalive_probes=5   
##优化网络设备接收队列   
net.core.netdev_max_backlog=3000

修改后使用 /sbin/sysctl -p让参数生效

如果服务器存在大量的close_wait。则表示代码没有调用close来被动关闭连接。请检查代码是否有对这种情况进行处理。。



发布了5 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/warlice/article/details/44218873