TIME-WAIT状态和reuse问题

前言

上一篇看了TCP的三次握手与四次挥手,记得四次挥手,主动断开连接的一方最后一个状态就是TIME-WAIT状态,并且一定是主动断开连接的一方,它可能使socket能陷入一种时间比较长的状态,过多的TIME-WAIT会影响新socket的建立。那么TIME-WAIT为什么会存在?它的作用又是什么呢?
TCP连接和断开连接状态转换图:
这里写图片描述

TIME-WAIT

从上图可以看到,客户端连接在收到服务器的结束报文段(6)之后,并没有直接进入CLOSED状态,而是转移到TIME-WAIT状态。此状态一般要等待2倍的MSL(报文段的最大生存时间)的时间,才能完全关闭。RFC 1122建议值为2min。
TIME-WAIT状态存在的原因有两点:

  1. 可靠地终止TCP连接
  2. 确保新TCP连接和老TCP连接不会相互干扰

原因1:可靠地终止TCP连接
其实就是确保“主动关闭”一端最后发出的ACK到达“被动关闭“的一端。假如用于确认服务器结束报文段6的TCP报文段7丢失了,那么服务器将会重发结束报文段。而客户端也就是主动断开的一端需要停留在某个状态重复收到结束报文段。假如客户端发送完ACK报文段后直接进入CLOSED状态,而最后的ACK报文段又丢失了,服务器进程会不断重发结束报文段,客户端则以复位报文段来回应服务器,服务器会认为这是个错误,因为它现在在等的是ACK报文段。
原因2:确保新TCP连接和老TCP连接不会相互干扰
Linux下,一个TCP端口不能被同时打开两次以上。当一个TCP连接处于TIME-WAIT状时,我们将无法立即使用该连接占用的端口来建立一个新连接。如果不存在TIME-WAIT状态,,应用程序再建立一个一样的连接,这时新连接又可能受到旧连接TCP报文段,这显然是不应该发生。
还有刚说过TIME-WAIT状态会维持2MSL的时间,而TCP报文段的最大生存时间是MSL,所以确保了网络上传输方向上的未被接受的、迟到的TCP报文段都已经消失。这也为什么要维持2MSL时间。

然而有时候我们又希望避免TIME-WAIT状态,当程序退出后我们可以立即重启它。例如百度腾讯这些大公司,如果真的哪天服务器崩掉了,必定是需要立即重启,要不然损失可就大了。
这里我用自己写的一个select服务器测试,发现先Ctrl+C之后,再次重新启动服务器,就会出错,这里就可以推测出,这里就是因为处在TIME-WAIT状态,端口被占用着,所以重新启动失败。那么怎么解决这个问题呢?
这里写图片描述

reuse问题

上图可以看到地址已经被用了
那么我们如何解决这个问题呢?
可以使用使用setsockopt函数

setsockopt函数

int setsockopt(int sockfd, int level, int optname,
              const void *optval, socklen_t optlen);
//可以在socket函数和bind函数之间加入这个函数
int on=1;
setsockopt(lisetn_sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))

SO_REUSEADDR是什么意思呢?

这个套接字通知内核,如果端口忙,而TCP处在TIME-WAIT状态时,可以重用端口。如果端口忙,而TCP不在TIME-WAIT,在其他状态时,仍然会得到一个错误信息,指明地址已在使用中。
另外SO_REUSEADDR选项提供的功能:

  1. SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则bind时将出错。
  2. SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。
  3. SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即可。这一般不用于TCP服务器。
  4. SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套接口而言(TCP不支持多播)。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值