热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

网络编程学习:07TIME_WAIT

关键词总结:TIME_WAIT代码路径见Github专栏代码TIME_WAIT发生的场景这要从TCP的四次挥手说起TCP连接终止时,主机1发送FI

关键词总结:TIME_WAIT

代码路径见Github 专栏代码

TIME_WAIT 发生的场景

这要从 TCP 的四次挥手说起
TCP 的四次挥手
TCP 连接终止时, 主机 1 发送FIN报文到主机2,主机2收到后进入CLOSE_WAIT,并发送一个ACK对主机2FIN报文应答;同时,主机 2 通过 read 调用获得 EOF,并将结果通知应用程序进行主动关闭操作,主机2发送FIN报文到主机1,主机1收到FIN报文后发送ACK对主机1FIN报文应答,此时主机 1 进入 TIME_WAIT 状态。
主机 1 在 TIME_WAIT 停留持续时间是固定的,是最长分节生命期 MSL(maximum segment lifetime)的两倍,一般称之为 2MSL。Linux 系统里有一个硬编码的字段,名称为TCP_TIMEWAIT_LEN,其值为 60 秒。也就是说,Linux 系统停留在 TIME_WAIT 的时间为固定的 60 秒

这个时间之后,主机 1 就进入 CLOSED 状态。只有发起连接终止的一方会进入 TIME_WAIT 状态

TIME_WAIT 的作用

1、为了确保最后的 ACK 能让被动关闭方接收(图中主机2),从而帮助其正常关闭。

如果由于某种原因导致主机1的ACK包(对主机2FIN包应答)没有传输成功,那么主机2就会重新发送FIN报文。

如果主机1没有维护 TIME_WAIT 状态,而直接进入 CLOSED 状态,它就失去了当前状态的上下文,接收不到主机2重传的FIN报文,只能回复一个 RST 操作,从而导致被动关闭方出现错误。

现在当主机 1 知道自己处于 TIME_WAIT 的状态,就可以在接收到 FIN 报文(主机2重传)之后,重新发出一个 ACK 报文,使得主机 2 可以进入正常的 CLOSED 状态。

2、让旧链接能够自然消失,避免迷走报文的误操作

在网络中,经常会发生报文经过一段时间才能到达目的地的情况,如果迷走报文到达时,发现 TCP 连接四元组(源 IP,源端口,目的 IP,目的端口)所代表的连接不复存在,那么很简单,这个报文自然丢弃。

但是,如果主机1和主机2断连后又重新创建了连接,这个连接和原先的连接四元组完全相同,如果迷失报文经过一段时间也到达(上个连接的报文),那么这个报文会被误认为是当前连接的,就会对 TCP 通信产生影响。

所以,TCP 就设计出了这么一个机制,经过 2MSL 这个时间,足以让两个方向上的迷走报文都被丢弃。2MSL 的时间是从主机 1 接收到 FIN 后发送 ACK 开始计时的;

TIME_WAIT 的危害

第一是内存资源占用,第二是对端口资源的占用
内存相对来说可以扩展,但是端口资源是有限的,一个 TCP 连接至少消耗一个本地端口。如果 TIME_WAIT 状态过多,会导致无法创建新连接。只有等一段时间之后,处于 TIME_WAIT 的连接被系统回收并关闭后,释放出本地端口才能新建连接。

如何优化 TIME_WAIT?

在高并发的情况下,如果我们想对 TIME_WAIT 做一些优化,该如何办呢?

net.ipv4.tcp_max_tw_buckets

一个暴力的方法是通过 sysctl 命令,将系统值调小。这个值默认为 18000,当系统中处于 TIME_WAIT 的连接一旦超过这个值时,系统就会将所有的 TIME_WAIT 连接状态重置,并且只打印出警告信息。治标不治本,带来的问题远比解决的问题多,不推荐使用。

调低 TCP_TIMEWAIT_LEN,重新编译系统

Linux 系统停留在 TIME_WAIT 的时间为固定的 60 秒。可以调低这个时间但是需要重新编译内核。

SO_LINGER 的设置

“linger”的意思为停留,可以通过设置套接字选项,来设置调用 close 或者 shutdown 关闭连接时的行为。
可以参见 setsockopt :SO_LINGER 选项设置

net.ipv4.tcp_tw_reuse:更安全的设置

Linux 系统对于net.ipv4.tcp_tw_reuse的解释如下:

Allow to reuse TIME-WAIT sockets for new connections when it is safe from protocol viewpoint. Default value is 0.It should not be changed without advice/request of technical experts.

大意是从协议角度理解如果是安全可控的,可以复用处于 TIME_WAIT 的套接字为新的连接所用。
那么什么是协议角度理解的安全可控呢?主要有两点:1、只适用于连接发起方(C/S 模型中的客户端);2、对应的 TIME_WAIT 状态的连接创建时间超过 1 秒才可以被复用。

使用这个选项,还有一个前提,需要打开对 TCP 时间戳的支持,即net.ipv4.tcp_timestamps=1(默认即为 1)。

参见 tcp_tw_reuse、tcp_tw_recycle 使用场景及注意事项

linux TIME_WAIT 相关参数:

net.ipv4.tcp_tw_reuse = 0 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭
net.ipv4.tcp_tw_recycle = 0 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭
net.ipv4.tcp_fin_timeout = 60 表示如果套接字由本端要求关闭,这个参数决定了它保持在FIN-WAIT-2状态的时间

注意:

  • 不像Windows 可以修改注册表修改2MSL 的值,linux 需要修改内核宏定义重新编译,tcp_fin_timeout 不是2MSL 而是Fin-WAIT-2状态超时时间.

  • tcp_tw_reuse 和 SO_REUSEADDR 是两个完全不同的东西
    SO_REUSEADDR 允许同时绑定 127.0.0.1 和 0.0.0.0 同一个端口; SO_RESUSEPORT linux 3.7才支持,用于绑定相同ip:port,像nginx 那样 fork方式也能实现


  1. tw_reuse,tw_recycle 必须在客户端和服务端 timestamps 开启时才管用(默认打开)

  2. tw_reuse 只对客户端起作用,开启后客户端在1s内回收

  3. tw_recycle 对客户端和服务器同时起作用,开启后在 3.5*RTO 内回收,RTO 200ms~ 120s 具体时间视网络状况。


参考资料:

网络编程实战(极客时间)链接:
http://gk.link/a/10g9X



GitHub链接:
https://github.com/lichangke
CSDN首页:
https://me.csdn.net/leacock1991
欢迎大家来一起交流学习


推荐阅读
  • 本文介绍了django中视图函数的使用方法,包括如何接收Web请求并返回Web响应,以及如何处理GET请求和POST请求。同时还介绍了urls.py和views.py文件的配置方式。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
author-avatar
Turkey小白
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有