1、为了在四次挥手中确保对方收到自己发送的ack。
2、为了防止原链接断开后又重新打开一个新的相同的链接(端口、ip、目的ip、目的端口都相同),迷走报文对新的链接产生影响。
TIME_WAIT的时间在LINUX下通常是设置为60s。有的系统设置为2MSL。
2MSL一般是从主机1接收到FIN后发送ACK开始计时到收到FIN为止的时间(RFC793中规定MSL的时间为2分钟,linux实际设置为30秒)
TIME_WAIT的危害
一、资源占用
二、对端口资源的占用
TIME_WAIT的优化
1、net.ipv4.tcp_max_tw_buckets
一个暴力的方法是通过sysctl命令,将系统值调小。这个值默认是18000,当系统处于TIME_WAIT的连接一旦超过这个值,系统就会将所有的TIME_WAIT链接状态重置,并且只打印警告信息。这个方法过于暴力,而且治标不治本,带来的问题远比解决的问题多,不推荐使用。
2、SO_LINGER设置 (可以跳过TIME_WAIT状态也可以设置TIME_WAIT的等待时间)
int setsockopt(int sockfd, int level, int optname, const void* optval, socklen_t optlen);
struct linger {
int l_onoff;
int l_linger;
}
- 如果l_onoff为非零,且l_linger的值也是非零,那么调用close后,调用close后的线程将会阻塞,直到数据被发送出去,或者设置的l_linger计时时间到。
struct linger so_linger;
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
setsockopt(s, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger));
- 如果l_onoff为非零,切l_linger的值为零,那么调用close后,会立即发送RST标志给对端,该TCP连接将跳过四次挥手,也就跳过了TIME_WAIT状态,直接关闭。这种关闭的方式称为“强行关闭”。在这种情况下,排队数据不会被发送,被动关闭方也不知道对端已经彻底断开。只有当被动关闭方正阻塞在recv()调用上时,接收到RST时,会立刻得到一个"connect reset by peer"的异常。
- 如果l_onoff为0,那么关闭本选项。l_linger的值被忽略,这对应了默认行为,close或shutdown立即返回。如果在套接字发送缓冲区中有数据残留,系统会试着把这些数据发送出去
3、net.ipv4.tcp_tw_reuse 可以复用socket