网络协议 -- TCP协议(3)TIME_WAIT及MSL
2018-01-30 15:56
731 查看
关于TCP的4次挥手过程参考:网络协议 – TCP协议(2)三次握手与四次挥手
在“主动断开连接端”收到了“被动断开连接端”发来的
归纳为一句话就是:TIME_WAIT状态就是“主动断开的一方”在发送完最后一次ACK后进入的等待状态。
《TCP/IP详解 卷1:协议》中提到:默认TIME_WAIT的超时时间是2倍的MSL。MSL是
查看默认的MSL值(60s):
修改默认为120:
修改完成后,重新加载配置文件:
查看是否已经生效:
如果一个服务端进程(绑定了某个端口)退出(正常退出或异常退出)后,立即启动一个新的该进程,可能由于Windows系统对端口的释放不及时,导致这个端口还没有被释放,不能被再次绑定,从而导致新进程绑定端口失败。
那么遇到上面的问题如何解决了?
我们在网络编程中经常设置的
SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则
SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。
SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。
SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套接口而言(TCP不支持多播)。
其中第一个功能就可以用来解决该问题。
一、TIME_WAIT状态为何存在?
这里我们不使用“客户端”、“服务端”来表示TCP连接的2端,转而使用“主动断开连接端”、“被动断开连接端”来表示TCP通讯的2端。因为执行主动断开连接的端可能是服务端也可能是客户端(虽然我们大多数情况下遇到的是客户端执行主动断开)。在“主动断开连接端”收到了“被动断开连接端”发来的
LAST_ACK之后,会给“被动断开连接端”回复一个
ACK确认消息。但这个时候为了确保“被动断开连接端”有足够的时间能够收到该消息,“主动断开连接端”不能马上关闭socket,需要等待一定的时间来确保“被动断开连接端”可以收到
ACK确认消息。“主动断开连接端”在等待的这个时间段内的状态我们称之为
TIME_WAIT状态。
归纳为一句话就是:TIME_WAIT状态就是“主动断开的一方”在发送完最后一次ACK后进入的等待状态。
二、等待时间
那么TIME_WAIT状态需要持续多久了,也就是“主动断开连接端”在发送完最后一个ACK之后需要等待多久了?
《TCP/IP详解 卷1:协议》中提到:默认TIME_WAIT的超时时间是2倍的MSL。MSL是
Maximum Segment Lifetime的缩写,表示报文的最大生存时间,这个时间和系统的TCP实现有关,每个系统是不一样的。
2.1 windows系统MSL
注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下的
TcpTimedWaitDelay键(如果没有可以新建一个)就对应了
2*MSL(2倍的MSL)的值。
2.2 Linux系统MSL
以CentOS为例(摘自网络,仅供参考):查看默认的MSL值(60s):
cat /proc/sys/net/ipv4/tcp_fin_timeout
修改默认为120:
echo 120 > /proc/sys/net/ipv4/tcp_fin_timeout
修改完成后,重新加载配置文件:
sysctl -p /etc/sysctl.conf
查看是否已经生效:
sysctl -a | grep fin
三、SO_REUSEADDR
如果进程中的某个TCP连接处于TIME_WAIT等待状态,因为这个等待时间比较长,在这期间该连接使用的端口将一直被占用。
如果一个服务端进程(绑定了某个端口)退出(正常退出或异常退出)后,立即启动一个新的该进程,可能由于Windows系统对端口的释放不及时,导致这个端口还没有被释放,不能被再次绑定,从而导致新进程绑定端口失败。
那么遇到上面的问题如何解决了?
我们在网络编程中经常设置的
SO_REUSEADDR选项就可以解决这个问题,
int flag = 1; setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&flag), sizeof(flag));
SO_REUSEADDR提供如下四个功能:
SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则
bind时将出错。
SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。
SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。
SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套接口而言(TCP不支持多播)。
其中第一个功能就可以用来解决该问题。
相关文章推荐
- TCP协议--TIME_WAIT状态
- TCP协议与UDP协议之间的九个区别-JAVA网络面试题
- 高性能网络里Time_wait状态过多
- linux 网络编程之TIME_WAIT状态
- 网络编程(10)—— 通过设置可选项取消socket的TImeWait状态以及开启Nagle算法
- 网络时间协议简介-----NTP(Network Time Protocol)
- TCP协议与UDP协议之间的九个区别-JAVA网络面试题
- Nginx网络连接timewait问题
- 网络基础与协议入门——(2)TCP协议重点
- 高性能网络 | 你所不知道的TIME_WAIT和CLOSE_WAIT
- TCP协议端口状态说明:CLOSE-WAIT、TIME-WAIT 、LISTENING、SYN_SENT、ESTABLISHED、LAST-ACK ...
- 网络编程中对TCP协议和UDP协议的理解
- 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程
- TCP协议的TIME_WAIT状态详解
- 20090802解决网站网络问题--出现大量TIME_WAIT 的问题
- 【Linux网络编程笔记】TCP短连接产生大量TIME_WAIT导致无法对外建立新TCP连接的原因及解决方法—实践篇
- 网络协议(UDP与TCP协议总结)
- 深入浅出TCP协议的2MSL TIME_WAIT状态
- linux 网络编程之TIME_WAIT状态
- Linux 网络编程之TIME_WAIT状态