当前位置:   article > 正文

TCP四次挥手终止连接的TIME_WAIT状态_tcp 断开timewait

tcp 断开timewait

(1)存在TIME_WAIT状态的原因

    首先,只有主动调用closed的一方才会在接收到对端的ACK后进入time_wait状态;并且任意一方都可以先发起closed;下图为四次挥手状态:

  • 原因一:保证TCP全双工连接的可靠释放

解析:假设场景为客户端主动向服务器发起断开连接,假如在主动方(客户端)最后一次发送的ACK在网络中丢失,根据TCP的超时重传机制,被动方(服务器)需要重新向客户端发送FIN+ACK,在FIN未达到之前,必须维护这条连接;并且要接收到客户端发出的ACK确认后才能终止连接;如果直接在重传的FIN到达之前而关闭连接,当FIN到达后会促使客户端TCP传输层发送RST重新建立连接,而本质上这是一个正常断开连接的过程。

另一种解释是:
       4次握手的最后一个ACK是是由主动关闭方发送出去的,若这个ACK丢失,被动关闭方会再次发一个FIN过来;若主动关闭方能够保持一个2MSL的TIME_WAIT状态,则有更大的机会让丢失的ACK被再次发送出去。

  • 原因二:为了使就得数据包在网络中因过期而失效

 解析:假设没有time_wait状态时,A刚刚与B断开连接,C又以和A相同的ip和port和B建立起连接,TCP协议栈无法区分A和C是不同的连接, 这时,A连接发送的数据到达B之后会被B的TCP传输层当做当下正常的连接发来的数据进行处理,实际上这时上一条连接的脏数据;所以在time_wait等待2MSL(报文在网络最大生存时间),将此连接的数据全部收到并丢弃,才能保证这些数据不会造成错误;
        为什么是两个2MSL的原因:如果不到2MSL就断开连接,新连接又以旧连接相同的端口和ip连接服务器,就连接的重复数据报到达又会干扰第二个连接;

(2)TIME_WAIT状态过多有何危害?如何解决TIME_WAIT过多情况?

  • 危害:占用太多资源,阻塞其他正常连接;
  • 解决方法

     第一种:首先服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口忙,但TCP连接位于TIME_WAIT状态时可以重用端口。在一个非常有用的场景就是,如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时SO_REUSEADDR选项就可以避免TIME_WAIT状态;
     情景分析案例:
       在服务器端值负责接收连接和和接受客户端的数据,在客户端,每创建一个连接就就往服务器发送两次数据,然后close关闭连接,那么客户端必定处理TIME_WAIT状态,如果再次启动客户端,客户端想继续使用同一个本地端口号,那么这个时候就需要使用SO_REUSEADDR进行设置;假如第一次创建的套接字对四元组为(cli:192.168.3.105:5678,server:192.168.3.108:8888),那么程序退出后5678处于TIME_WAIT状态, 使用这个套接字选项保证可以继续使用这个本地端口号。

第二种:修改内核参数来减少time_wait状态?

编辑文件/etc/sysctl.conf,加入以下内容
    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,表示关闭
    net.ipv4.tcp_fin_timeout = 30  //表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间。
 注意:reuse是表示是否允许重新应用处于TIME-WAIT状态的socket用于新的TCP连接; recyse是加速TIME-WAIT sockets回收

(3)如果修改修改time_wait的时间有什么影响?

如果修改time_wait的时间会造成上一个连接的数据没有完全接收到,会重建连接错误;另一个是造成新建的连接出现错误,收到不期望收到的数据;
注意:Linux是无法修改tcp的time_wait值的;

(4)netstat 命令的使用

  • netstat -ant  查看time_wait状态  
  •  netsat -i 打印端口信息  
  • netstat -n 打印ip地址  
  • netstat -rn 打印路由表信息
  • netstat  -n | awk    '/^tcp/{++S[$NF]}END{for (key in S) print key,S[key]}'

    time_wait:
    FIN_WAIT 1:
    FIN_WAIT 2:
    ESTABLISHED
    SYN_RECV:        

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/程序诗人/article/detail/60155
推荐阅读
相关标签
  

闽ICP备14008679号