2MSL (Maximum Segment Lifetime) TIME_WAIT状态的存在有两个理由:

(1)让4次握手关闭流程更加可靠;4次握手的最后一个ACK是由主动关闭方发送出去的,若这个ACK丢失,被动关闭方会再次发一个FIN过来。若主动关闭方能够保持一个2MSL的TIME_WAIT状态,则有更大的机会让丢失的ACK被再次发送出去。
  (2)防止lost duplicate对后续新建正常链接的传输造成破坏。lost duplicate在实际的网络中非常常见,经常是由于路由器产生故障,路径无法收敛,导致一个packet在路由器A,B,C之间做类似死循环的跳转。IP头部有个TTL,限制了一个包在网络中的最大跳数,因此这个包有两种命运,要么最后TTL变为0,在网络中消失;要么TTL在变为0之前路由器路径收敛,它凭借剩余的TTL跳数终于到达目的地。但非常可惜的是TCP通过超时重传机制在早些时候发送了一个跟它一模一样的包,并先于它达到了目的地,因此它的命运也就注定被TCP协议栈抛弃。
  
  另外一个概念叫做incarnation connection,指跟上次的socket pair一摸一样的新连接,叫做incarnation of previous connection。lost duplicate加上incarnation connection,则会对我们的传输造成致命的错误。
  
  TCP是流式的,所有包到达的顺序是不一致的,依靠序列号由TCP协议栈做顺序的拼接;假设一个incarnation connection这时收到的seq=1000, 来了一个lost duplicate为seq=1000,len=1000, 则TCP认为这个lost duplicate合法,并存放入了receive buffer,导致传输出现错误。通过一个2MSL TIME_WAIT状态,确保所有的lost duplicate都会消失掉,避免对新连接造成错误。
  
  该状态为什么设计在主动关闭这一方:
  (1)发最后ACK的是主动关闭一方。
  (2)只要有一方保持TIME_WAIT状态,就能起到避免incarnation connection在2MSL内的重新建立,不需要两方都有。
  如何正确对待2MSL TIME_WAIT?
  RFC要求socket pair在处于TIME_WAIT时,不能再起一个incarnation connection。但绝大部分TCP实现,强加了更为严格的限制。在2MSL等待期间,socket中使用的本地端口在默认情况下不能再被使用。
  若A 10.234.5.5 : 1234和B 10.55.55.60 : 6666建立了连接,A主动关闭,那么在A端只要port为1234,无论对方的port和ip是什么,都不允许再起服务。这甚至比RFC限制更为严格,RFC仅仅是要求socket pair不一致,而实现当中只要这个port处于TIME_WAIT,就不允许起连接。这个限制对主动打开方来说是无所谓的,因为一般用的是临时端口;但对于被动打开方,一般是server,就悲剧了,因为server一般是熟知端口。比如http,一般端口是80,不可能允许这个服务在2MSL内不能起来。
  解决方案是给服务器的socket设置SO_REUSEADDR选项,这样的话就算熟知端口处于TIME_WAIT状态,在这个端口上依旧可以将服务启动。当然,虽然有了SO_REUSEADDR选项,但sockt pair这个限制依旧存在。比如上面的例子,A通过SO_REUSEADDR选项依旧在1234端口上起了监听,但这时我们若是从B通过6666端口去连它,TCP协议会告诉我们连接失败,原因为Address already in use.
  RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。
  RFC (Request For Comments),是一系列以编号排定的文件。收集了有关因特网相关资讯,以及UNIX和因特网社群的软件文件。

程序设计中的问题

做一个测试,首先启动server,然后启动client,用Ctrl-C终止server,马上再运行server,运行结果:
$ ./server
bind error: Address already in use
  这是因为,虽然server的应用程序终止了,但TCP协议层的连接并没有完全断开,因此不能再次监听同样的server端口。我们用netstat命令查看一下:
$ netstat -apn |grep 6666
tcp 1 0 192.168.1.11:38103 192.168.1.11:6666 CLOSE_WAIT 3525/client
tcp 0 0 192.168.1.11:6666 192.168.1.11:38103 FIN_WAIT2 -
  server终止时,socket描述符会自动关闭并发FIN段给client,client收到FIN后处于CLOSE_WAIT状态,但是client并没有终止,也没有关闭socket描述符,因此不会发FIN给server,因此server的TCP连接处于FIN_WAIT2状态。
  现在用Ctrl-C把client也终止掉,再观察现象:
$ netstat -apn |grep 6666
tcp 0 0 192.168.1.11:6666 192.168.1.11:38104 TIME_WAIT -
$ ./server
bind error: Address already in use
  client终止时自动关闭socket描述符,server的TCP连接收到client发的FIN段后处于TIME_WAIT状态。TCP协议规定,主动关闭连接的一方要处于TIME_WAIT状态,等待两个MSL(maximum segment lifetime)的时间后才能回到CLOSED状态,因为我们先Ctrl-C终止了server,所以server是主动关闭连接的一方,在TIME_WAIT期间仍然不能再次监听同样的server端口。
  
  MSL在RFC 1122中规定为两分钟,但是各操作系统的实现不同,在Linux上一般经过半分钟后就可以再次启动server了。

2MSL (Maximum Segment Lifetime)相关推荐

  1. TCP第四次挥手为什么要等待2MSL(最长报文段寿命,Maximum Segment Lifetime)

    当客户端进入TIME-WAIT状态的时候(也就是第四次挥手的时候),必须经过时间计数器设置的时间2MSL(最长报文段寿命)后,才能进入关闭状态,这时为什么呢??? 这最主要是因为两个理由: 1.为了保 ...

  2. TCP四次挥手 2MSL TIME_WAIT详解

    TCP四次挥手 & 2MSL & TIME_WAIT详解 TCP四次挥手流程 各状态解析 2MSL(2倍最大报文段生成时间) 2MSL (Maximum Segment Lifetim ...

  3. Linux内核TCP/IP参数分析与调优

    如图展示的是TCP的三个阶段.1,TCP三次握手. 2,TCP数据传输. 3,TCP的四次挥手. SYN:(同步序列编号,Synchronize Sequence Numbers)该标志仅在三次握手建 ...

  4. 你应该知道的计算机网络知识

    前言 作为一名程序员, 不可能不与网络打交道. 现在我们的手机, 电脑, 不夸张地说, 离开了网络就是一块'废铁', 它们的作用将大打折扣.. 本文的作用呢, 主要是针对不是非网络专业开发的人员准备的 ...

  5. 拉勾网《32个Java面试必考点》学习笔记之二------操作系统与网络知识

    本文为拉勾网<32个Java面试必考点>学习笔记.只是对视频内容进行简单整理,详细内容还请自行观看视频<32个Java面试必考点>.若本文侵犯了相关所有者的权益,请联系:txz ...

  6. 网络基础4(TCP三次握手,四次握手,TCP流量控制,TCP状态转换 , TCP异常断开,设置TCP属性,端口复用)

    TCP协议 TCP通信时序 下图是一次TCP通讯的时序图.TCP连接建立断开.包含大家熟知的三次握手和四次握手. TCP通讯时序 在这个例子中,首先客户端主动发起连接.发送请求,然后服务器端响应请求, ...

  7. C++笔记--Linux网络编程(15-0)-socket(供自查,文档说明)

    目录 网络基础 协议的概念 什么是协议 典型协议 网络应用程序设计模式 C/S模式 B/S模式 优缺点 分层模型 OSI七层模型 TCP/IP四层模型 通信过程 协议格式 数据包封装 以太网帧格式 A ...

  8. linux服务器开发三(网络编程)

    转载自:http://www.cnblogs.com/zfc2201/archive/2017/05/04/6804990.html 作者:水之原 网络基础 协议的概念 什么是协议 从应用的角度出发, ...

  9. zz-tcp参数配置

    刘超-趣谈网络协议 链接:https://pan.baidu.com/s/1DCNesLnA94_B3Xu5Jdg51A  提取码:1u4u https://www.cnblogs.com/zengk ...

最新文章

  1. Fins TCP协议
  2. 国内网络安全这门行业人才会不会饱和呢?
  3. Writing for Myself.part2
  4. java java se_Java SE 7、8、9 –推动Java前进
  5. matlab语音去除白噪声_全国首款“AI语音电梯”亮相海淀医院、北医三院
  6. linux用户limit修改,linux – 使用cgroups作为用户设置用户创建的systemd范围的MemoryLimit...
  7. Eviews 9.0新功能——估计方法(ARDL、面板自回归、门限回归)
  8. m序列产生原理及其性质
  9. Hive SQL之表与建表
  10. bom实现方块移动_js实现方块上下左右移动效果
  11. 2022中国汽车测试及质量监控博览会邀请函
  12. 谷歌Flan-T5诞生!1800种语言任务超大规模微调
  13. 升级鸿蒙系统手机网络信号变差了,这是为什么?
  14. qt creator插入代码块快速注释snippets代码片段的功能
  15. 如何使用ArcMap连接PostGresql(包含PostGresql和PostGis以及所需要的安装文件的下载链接)
  16. 大数据日志分析项目mapreduce程序
  17. mysql 查询 及时间格式化
  18. 用电脑自带的“画图”调整图片大小到100K以下
  19. 万字长文!深度剖析《数据安全法》下多方数据协同应用和隐私计算发展趋势
  20. c语言遍历json数组,如何使用c动态获取所有json元素?

热门文章

  1. 苏宁董事长张近东辞职,提名张康阳非独立董事候选人
  2. js构造函数创建对象
  3. fre 更新了,框架设计重思考……
  4. 实现判断电话号码格式是否正确
  5. 规范的Java注释模板设置
  6. 专题测试02·一元函数微分学【李艳芳全程班】
  7. 光闸mysql同步_mysql跨网域canal数据同步
  8. 如何自动安装CA证书
  9. 必须有数字和字母组合的密码正则表达式
  10. 异步请求-XMLHttpRequest、ajax、axios原理浅析