【零散随笔】深入理解TIME_WAIT及相关问题

小引:在我之前的几篇TCP与UDP服务器的实现中没有注意到TIME_WAIT这个细节,引来了一个问题。就是我在调试的时候,想要重启一下服务器,直接ctrl+c然后重选上一个命令。我发现总是会给我报出一个bind error: Address already in use的错误,为什么会绑定出错呢,我根据提示地址已经被使用,输入了netstat -anp tcp查看到我的端口还没有被关闭,可我明明已经ctrl+c了呀。


TIME_WAIT是指在四次挥手的第四次时服务器向客户端发送FIN请求,客户端收到FIN请求后进入TIME_WAIT时间,然后客户端再向服务器发送FIN_ACK,服务器收到FIN_ACK之后关闭连接。

为什么会有TIME_WAIT?TIME_WAIT对链接结束过程有什么影响?

1.本质:将等待的时间交给客户端,避免降低服务器的性能。

我们可以假设没有TIME_WAIT,客户端收到FIN并发送FIN_ACK之后立即关闭。如果该FIN_ACK丢失,服务器会认为,自己发的FIN请求没有被收到,于是会再次发送FIN请求,但是此时客户端已经关闭,所以不会再回复。服务器就会进入反复FIN请求的状态,多次没收到回复之后再断开该客户端的链接,大量消耗服务器资源,是极其不合理的。

如果有TIME_WAIT,再发生上述的FIN_ACK丢失,此时客户端套接字还没有关闭,再次收到FIN请求后,能够快速重发FIN_ACK,这样就极大的避免了服务器等待已关闭链接的情况。

如果TIME_WAIT期间,客户端没有再次收到FIN请求,此时对于客户端来说,没有消息就是好消息,客户端会认为服务器已经收到了FIN_ACK并关闭了套接字。然后TIME_WAIT时间结束后,客户端再去销毁自己的套接字。

因此TIME_WAIT的时间被设置为2MSL(Max Segment Life)的时间。

2.额外:TIME_WAIT期间,还可以让通信信道中链接时的正常数据尽量不要丢失。

数据在没有TCP,只有IP层的时候,有可能出现乱序的情况。也就是说,如果两者发送的正常数据不幸被阻塞在链接途径中的某台路由器上,但是发送关闭链接请求时,路由器发现之前有数据阻塞,零时调整了算法,导致后发的关闭链接请求先于正常数据到达,如果没有TIME_WAIT时间,迟到的正常数据就无法被接收,因而造成数据缺失。

TIME_WAIT带来的问题?

首先要知道两点服务器主动断开连接时,会进入TIME_WAIT状态

TIMEWAIT期间客户端并没有CLOSE,所以我们认为此时链接还没有断开

bind error: Address already in use

服务器一旦挂掉,链接还没有立即断开,服务器和客户端的一对套接字还在被占用,端口号也还在被占用,所以此时立刻重启服务器,就会出现绑定错误,因为端口号还在被占用。

解决方法:

1.(简单粗暴)

换个端口号把服务器开起来

2.opt

在操作系统层面认为,如果你的链接进入TIMEWAIT状态,服务也就接近尾声,所以即便是TIMEWAIT状态,也允许端口号,被再次绑定。也就有了如下接口来实现该属性。

使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1,表示允许创建端口号相同,但ip地址不同的套接字。

在ser端代码的socket()和bind()之间插入如下代码

int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值