TCP TIME_WAIT状态(2MSL)

转帖网址:http://hi.baidu.com/packetslost/blog/item/ea8bc9c398be9551b219a836.html

 

TCP TIME_WAIT状态(2MSL)
2008-02-26 11:12

------Finger

一般来说,tcp正常关闭需要四个包。比如a和b关闭连接,a先 给b发一个fin,b会进行确认ack,然后b也会发出fin,当a接受到这个fin,并发出最后一个ack后,就会处于time_wait状态。这个时 间长短跟操作系统有关,一般会在1-4分钟,也就是两倍的数据包(2msl)最大生存时间。TCP主动关闭方采用TIME_WAIT主要是为了实现终止 TCP全双工连接的可靠性及允许老的重复分节在网络中消逝,等过了2msl(大约1~4分钟)后TIME_WAIT就会消失。   
TIME_WAIT状态的目的是为了防止最后a发出的ack丢失,让b处于LAST_ACK超时重发FIN


   所以说,主动发起关闭连接的一方会进入time_wait状态,这个时候,进程所占用的端口号不能被释放。除非在你的程序中用setsockopt设置端口可重用(SOCK_REUSE)的选项,但这不是所有操作系统都支持的


   解决TIME_WAIT的办法主要有以下几种:    


   1、修改LINGER值,缩短关闭时间
   LINGER    lingerStruct;
   lingerStruct.l_onoff    =    1;
   lingerStruct.l_linger     =    0;
   setsockopt(m_socket,SOL_SOCKET,SO_LINGER,(char *)&lingerStruct,sizeof(lingerStruct));
   不过这种办法不是很安全的,不过现在网络都很好啦,不会有问题的。

   2、修改注册表
   [HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/Services/Tcpip/Parameters]
   "TcpTimedWaitDelay"=dword:00000005
   这个值好像是300秒到30秒之间,改成30秒后你会发现TIME_WAIT很快就会消失了。


   3、禁用LINGER
   //如果你使用的是Socket API,可以这样
   BOOL bDontLinger=FALSE;      
   setsockopt(m_socket,SOL_SOCKET,SO_DONTLINGER,(LPCTSTR)&bDontLinger,sizeof(BOOL));
   closesocket(s);

   //如果你使用的是CAsyncSocket,需要响应的修改,例如禁用LINGER可以这样
   BOOL bDontLinger=FALSE;   
   m_socket->SetSockOpt(SO_DONTLINGER,(const char *)&bDontLinger,sizeof(bDontLinger),SOL_SOCKET);
   m_socket->Close();

   4、客户端可以不BIND(),这样,即使断开连接后再次连接,SOCKET将使用不同的端口(1025-5000),
   等几分钟后,原有的端口就会自动关闭。

关闭BITCOMET后系统出现的几个TCP状态

 

公司linux apache服务器,用netstat -an命令发现服务器中有大量状态为TIME-WAIT的TCP连接,
于是用/sbin/sysctl -a查看了一下Linux的各项内核参数,
并翻阅有关资料和网上的各种资料,最后修改其中的两项参数,即可减少TCP连接中TIME-WAIT sockets的目的。
#vi /etc/sysctl.conf
编辑/etc/sysctl.conf文件,增加三行:
引用
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
说明:
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
让修改结果立即生效:(执行下面命令)
#/sbin/sysctl -pa
用以下语句看了一下服务器的TCP状态:
#netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
返回结果如下:
ESTABLISHED 1423
FIN_WAIT1 1
FIN_WAIT2 262
SYN_SENT 1
TIME_WAIT 962
效果:处于TIME_WAIT状态的sockets从原来的10000多减少到1000左右。处于SYN_RECV等待处理状态的sockets为0,原来的为50~300。
源文档 <http://www.zongguofeng.cn/article/2009/0121/article_147.html>

 

你可能感兴趣的:(TCP TIME_WAIT状态(2MSL))