【网络】简单聊一下 TIME_WAIT

问题背景

笔者在看自己服务状态数据的时候,会发现有很多 tcp 的连接,也会发现有很多处于不同状态下的 tcp 连接,TIME_WAIT 的连接数有83个,为了弄清楚这个 TIME_WAIT 是什么,整理了下面的笔记用于梳理概念
在这里插入图片描述

基础流程

TCP的三次握手和四次挥手是TCP协议建立和终止连接的基本过程。

在这里插入图片描述

三次握手过程如下:

  1. 客户端发送SYN包(同步序列编号)给服务器,等待服务器确认。
  2. 服务器收到SYN包后,会确认客户的SYN(发送一个ACK),同时也会发送一个SYN包,这个步骤称为SYN+ACK。
  3. 客户端收到服务器的SYN+ACK后,还需向服务器发送确认包ACK。至此,完成三次握手,客户端和服务器开始传送数据。

四次挥手过程如下:

  1. 当数据传送完毕后,客户端会发送一个FIN包给服务器,请求关闭连接。
  2. 服务器收到FIN包后,会发送一个ACK给客户端,确认接收到了FIN包,但不会立即关闭连接,因为服务器可能还有数据需要处理和发送。
  3. 当服务器数据发送完毕后,会向客户端发送FIN包,请求关闭连接。
  4. 客户端收到FIN包后,会发送一个ACK给服务器,然后进入TIME_WAIT状态。TIME_WAIT状态持续一段时间后,如果没有再收到服务器的消息,那么就关闭连接。至此,完成四次挥手。

为什么有 TIME_WAIT

TIME_WAIT状态在TCP四次挥手的最后阶段出现。在TCP连接被关闭后,操作系统会等待一段时间(通常是2倍的最大分段生存时间),以确保对方收到了关闭连接的确认。这个等待时间就是TIME_WAIT。对于复杂的网络状态,TCP 的实现提出了多种应对措施,TIME_WAIT 状态的提出就是为了应对其中一种异常状况。 此状态的存在主要有两个原因:

  1. 保证最后一个确认消息能被对方收到。如果直接关闭连接,那么对方可能会因为没有收到确认消息而无法关闭连接。
  2. 避免“旧的重复分组”在新的连接中被错误接收。由于网络原因,有可能会有一些旧的重复分组在网络中滞留,如果直接开启新的连接,这些旧的重复分组可能会被新的连接误认为是自己的数据。

为了理解 TIME_WAIT 状态的必要性,我们先来假设没有这么一种状态会导致的问题。暂以 A、B 来代指 TCP 连接的两端,A 为主动关闭的一端。

  • 四次挥手中,A 发 FIN, B 响应 ACK,B 再发 FIN,A 响应 ACK 实现连接的关闭。而如果 A 响应的 ACK 包丢失,B 会以为 A 没有收到自己的关闭请求,然后会重试向 A 再发 FIN 包。

    如果没有 TIME_WAIT 状态,那么A回复ACK立刻关闭,所以B重发的会让A响应重置,A 不再保存这个连接的信息,收到一个不存在的连接的包,A 会响应 RST 包,导致 B 端异常响应。

    此时, TIME_WAIT 是为了保证全双工的 TCP 连接正常终止。

  • 我们还知道,TCP 下的 IP 层协议是无法保证包传输的先后顺序的。如果双方挥手之后,一个网络四元组(src/dst ip/port)被回收,而此时网络中还有一个迟到的数据包没有被 B 接收,A 应用程序又立刻使用了同样的四元组再创建了一个新的连接后,这个迟到的数据包才到达 B,那么这个数据包就会让 B 以为是 A 刚发过来的。

    此时, TIME_WAIT 的存在是为了保证网络中迷失的数据包正常过期。

不同场景下的 TIME_WAIT 的具体影响

基于不同的使用场景,我们一般区分为“长连接”和“短连接”

长链接

长连接,指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包。

是一种在客户端和服务器之间维持长时间连接的通信机制。与传统的短链接请求-响应模型不同,长链接允许客户端向服务器发出请求并保持连接打开,以等待服务器在有数据更新时立即响应。

长链接的工作原理通常如下:

  1. 客户端发起连接请求: 客户端向服务器发送一个连接请求。
  2. 服务器保持连接打开: 服务器接收到连接请求后,保持连接打开并等待数据变化或其他事件的发生。
  3. 服务器响应: 当服务器有数据更新或满足其他条件时,它立即响应客户端请求,并发送数据给客户端。
  4. 客户端处理响应: 客户端接收到服务器的响应后,可以处理数据更新或执行其他操作。
  5. 连接保持开放: 连接保持开放,客户端和服务器可以继续在连接上进行通信。

长连接的优点是:

这种长链接机制的优势在于实时性更强,因为服务器可以立即将更新推送给客户端,而无需等待客户端发起新的请求。这对于实时通信、即时消息推送以及需要及时获取数据更新的应用场景非常有用。

  • 减少了建立连接和断开连接的开销,提高了传输效率。
  • 减少了连接数,节省了服务器资源。
  • 便于维护和管理。

长连接的缺点是:

长链接也有一些缺点,例如在一些网络环境中可能存在连接超时的问题,而且在维持大量长连接时可能增加服务器的负载。因此,开发人员需要根据具体的应用场景和需求来选择适当的通信机制。

  • 可能会导致连接泄漏,造成资源浪费。
  • 可能会导致连接超时,影响传输效率。

长连接的应用场景包括:

  • 聊天软件:客户端和服务器之间需要保持长连接,以便及时交换消息。
  • 文件传输:服务器和客户端之间需要保持长连接,以便传输大文件。
  • 实时数据传输:服务器和客户端之间需要保持长连接,以便实时传输数据。
package mainimport ("fmt""net""time"
)func handleLongConnection(conn net.Conn) {defer conn.Close()for {// 读取客户端发送的数据buffer := make([]byte, 1024)_, err := conn.Read(buffer)if err != nil {fmt.Println("Error reading:", err)return}// 处理数据fmt.Println("Received:", string(buffer))// 模拟长连接,等待一段时间再回复客户端time.Sleep(time.Second * 5)// 向客户端发送响应response := []byte("Server response")conn.Write(response)}
}func main() {listener, err := net.Listen("tcp", ":8080")if err != nil {fmt.Println("Error listening:", err)return}defer listener.Close()fmt.Println("Server listening on :8080 for long connection")for {conn, err := listener.Accept()if err != nil {fmt.Println("Error accepting connection:", err)continue}// 启动长连接处理协程go handleLongConnection(conn)}
}

短连接

短连接是指在数据传送过程中,只在需要发送数据时,才去建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。

在计算机网络中,短连接(short connection)是指在数据传送过程中,只在需要发送数据时,才去建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送。

短连接的优点是**:**

  1. 资源释放: 短连接在完成数据传输后会立即释放资源,不需要维持长时间的连接状态,因此能够更有效地释放系统资源。
  2. 简单易实现: 短连接模型相对简单,易于实现和维护。每个请求都是独立的,不需要维持连接状态。
  3. 连接灵活性: 短连接适用于一些场景,如HTTP请求,每次请求都是独立的,适合短暂的数据交互。
  4. 适用于并发: 短连接模型适用于并发连接,因为每个连接都是独立的,不会影响其他连接。

短连接的缺点是:

  1. 连接建立开销: 每次建立连接都需要进行握手过程,包括TCP的三次握手,这会增加网络开销。
  2. 频繁的连接断开和建立: 对于高频率的短连接,频繁的连接断开和建立可能会增加系统开销,尤其是在高并发的情况下。
  3. 维护开销: 如果应用中存在频繁的连接建立和断开,服务器需要维护大量的连接状态信息,可能会增加服务器的负担。
  4. 实时性差: 短连接可能无法满足实时性要求较高的应用场景,因为连接建立和断开的开销可能影响数据的实时传输。

短连接的应用场景包括:

  • 浏览器和服务器之间的HTTP请求。
  • 邮件服务器和客户端之间的SMTP/POP3/IMAP协议。
  • 聊天软件客户端和服务器之间的聊天协议。
package mainimport ("fmt""net"
)func handleShortConnection(conn net.Conn) {defer conn.Close()// 读取客户端发送的数据buffer := make([]byte, 1024)_, err := conn.Read(buffer)if err != nil {fmt.Println("Error reading:", err)return}// 处理数据fmt.Println("Received:", string(buffer))// 向客户端发送响应response := []byte("Server response")conn.Write(response)
}func main() {listener, err := net.Listen("tcp", ":8081")if err != nil {fmt.Println("Error listening:", err)return}defer listener.Close()fmt.Println("Server listening on :8081 for short connection")for {conn, err := listener.Accept()if err != nil {fmt.Println("Error accepting connection:", err)continue}// 启动短连接处理handleShortConnection(conn)}
}

正常的TCP客户端连接在关闭后,会进入一个TIME_WAIT的状态,持续的时间一般在1~4分钟,如果短时间内(例如1s内)进行大量的短连接,则可能出现这样一种情况:客户端所在的操作系统的socket端口和句柄被用尽,系统无法再发起新的连接!如果 TIME_WAIT 连接过多,会消耗大量的系统资源,会耗尽可用的网络端口,从而阻止新的连接建立。因此,对于处于 TIME_WAIT 状态的连接,需要进行合理的管理和控制。

举例来说:假设每秒建立了1000个短连接(Web场景下是很常见的,例如每个请求都去访问),假设TIME_WAIT的时间是1分钟,则1分钟内需要建立6W个短连接,由于TIME_WAIT时间是1分钟,这些短连接1分钟内都处于TIME_WAIT状态,都不会释放,而Linux默认的本地端口范围配置是:net.ipv4.ip_local_port_range = 32768 ~ 61000 不到3W,因此这种情况下新的请求由于没有本地端口就不能建立了。

缓解办法

代码侧

GOLANG

go 里面 Transport 默认参数有个 MaxIdleConns 是100,还有 Timeout 是 90s,这两个参数会导致 client 自动发起 FIN,代码侧可以优化这边的逻辑,不同的语言应该有对应的优化方法。

在这里插入图片描述

系统侧

在TCP连接中,TIME_WAIT状态是在连接关闭后等待一段时间的状态,以确保对方收到了最后的ACK。这是为了处理网络中的滞留数据报文(可能在网络中延迟到达),防止它们被新的连接误认为是旧的连接的问题。

降低TIME_WAIT状态对于提高连接的重用速度是有风险的,因为它可能导致旧的数据报文在网络中被混淆。然而,如果你仍然想要降低TIME_WAIT状态的等待时间,可以在系统上进行一些调整。请注意,对于这样的操作,你应该非常小心,因为它可能会对网络稳定性产生负面影响。

在Linux系统上,你可以通过修改内核参数来调整TIME_WAIT状态的等待时间。

  • net.ipv4.tcp_max_tw_buckets:指定系统同时保持 TIME_WAIT 的最大数量。
  • net.ipv4.tcp_tw_reuse:如果设置为 1,则允许 TIME_WAIT 状态的连接被重用。
  • net.ipv4.tcp_tw_recycle:如果设置为 1,则允许 TIME_WAIT 状态的连接在 FIN_WAIT-2 状态时被快速回收。

以下是一些可能的方法:

方法一:通过sysctl修改

通过sysctl可以动态地调整内核参数。

sudo sysctl -w net.ipv4.tcp_tw_reuse=1
sudo sysctl -w net.ipv4.tcp_tw_recycle=1
  • net.ipv4.tcp_tw_reuse=1 允许将TIME_WAIT状态的连接端口重用。
  • net.ipv4.tcp_tw_recycle=1 尝试根据时间戳来快速回收TIME_WAIT状态的连接。

这种方法修改是暂时的,重启后会失效。

方法二:修改sysctl配置文件

将上述配置添加到 /etc/sysctl.conf 文件中,以便在系统启动时应用。

echo "net.ipv4.tcp_tw_reuse=1" | sudo tee -a /etc/sysctl.conf
echo "net.ipv4.tcp_tw_recycle=1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

这种方法在系统重启后仍然有效。

请注意,在一些情况下,使用 net.ipv4.tcp_tw_recycle 可能会导致问题,因为它可能与一些网络设备不兼容。在生产环境中,修改这些参数前应该进行充分测试,以确保它们不会对系统的稳定性和性能产生负面影响。

总的来说,TIME_WAIT 是TCP连接管理中的一个重要环节,尽管它可能会引发一些问题,但适当的管理和调优可以最大程度地减轻这些问题的影响,保证网络连接的正常运行。

总结

在 Go 中,HTTP客户端(例如**http.Client**)发起的HTTP请求的完成过程可能涉及到TCP连接的正常关闭,从而触发发送TCP FIN(Finish)标志。这是正常的TCP连接关闭行为,其触发条件包括:

  1. HTTP请求完成: 当HTTP请求完成(例如,成功获取到响应或发生错误)时,客户端的**http.Transport**可能会将连接放回到连接池以便复用,或者决定是否关闭连接。
  2. 连接池空闲时: 如果连接池中没有空闲的连接,并且该连接也没有被标记为永久保持活跃(通过**Transport.DisableKeepAlives**设置),那么连接可能会被关闭。
  3. 达到最大空闲连接数: 如果连接池中的连接数量达到了 http.TransportMaxIdleConnsMaxIdleConnsPerHost 设置的最大空闲连接数,那么一些连接可能会被关闭。
  4. 连接过期: http.Transport 会根据连接的空闲时间进行管理。如果连接在一段时间内未被使用,可能会被关闭。

这些操作是为了维护连接池的健康状态,确保连接的新鲜性,并防止长时间空闲的连接占用资源。触发TCP FIN标志是连接关闭的一部分,用于通知对端连接即将关闭。

引用

CHATGPT

BARD

https://www.xiaolincoding.com/network/3_tcp/tcp_tcpdump.html#解密-tcp-三次握手和四次挥手

https://claire-chang.com/2020/03/01/tcp連線階段與time_wait意義/

https://zhenbianshu.github.io/2018/12/talk_about_tcp_timewait.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218352.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rocketmq window测试小Demo 解决找不到或无法加载主类的问题

文章目录 rocketMQ启动1.下在相关的二进制文件2.配置环境变量3.启动NameServer4.启动broker5. MQ 启动!5.1 测试发送数据 6.关闭服务 rocketMQ启动 1.下在相关的二进制文件 下载地址,点击即达 2.配置环境变量 3.启动NameServer 在文件夹下执行cmd进…

vue项目 实现 vue-schart 图表 resize

项目中之前用了 vue-schart&#xff08;项目已经没人维护&#xff0c;很久不更新了&#xff09; GitHub - lin-xin/vue-schart: :bar_chart: Vue.js wrapper for sChart.js 没有resize功能&#xff0c;又不想修改源码&#xff0c;可以参考下边的方法实现&#xff1a; <tem…

Redis7--基础篇9(SpringBoot集成Redis)

1. jedis、lettuce、Redistemplate的关系 第一代为jedis&#xff0c;之后推出了lettuce&#xff0c;然后springboot继承了Redistemplate&#xff0c;现推荐使用Redistemplate。 总的来说&#xff0c;jedis、lettuce、Redistemplate都是java操作Redis数据库的驱动。 2. 本地Ja…

【精选小tips】Microsoft Edge最新版本关闭侧边栏快捷键

相信有很多小伙伴并不习惯使用Edge浏览器的侧边栏功能&#xff0c;感觉有点突兀&#xff0c;平时使用率又不是很高&#xff0c;想要将其关闭&#xff0c;但是&#xff01;&#xff01;&#xff01;Edge浏览器自动更新到120.0.2210.61版本后&#xff0c;居然在设置中之间没有了关…

深度学习(六):paddleOCR理解及识别手写体,手写公式,表格

1.介绍 1.1 什么是OCR? 光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;&#xff0c;ORC是指对包含文本资料的图像文件进行分析识别处理&#xff0c;获取文字及版面信息的技术&#xff0c;检测图像中的文本资料&#xff0c;并且识别出文本的内容。…

传谷歌拟在广告中使用新AI模型,并为YouTuber提供建议

原标题&#xff1a;传谷歌(GOOG.US)拟在广告中使用新AI模型 并为YouTuber提供建议 智通财经 APP 获悉&#xff0c;据报道&#xff0c;谷歌正努力将新的人工智能技术迅速融入其核心产品&#xff0c;且这一努力正在进入广告领域。据内部文件显示&#xff0c;该公司已经批准了在大…

一键删除TXT文本符号,高效批量处理,轻松提升工作效率!

你是否经常处理大量的TXT文本文件&#xff0c;但其中充满了各种符号和不需要的字符&#xff1f;这不仅影响文本的阅读体验&#xff0c;还可能对后续的数据处理和分析造成困扰。现在&#xff0c;我们为你带来一款全新的TXT文本处理工具&#xff0c;一键删除符号&#xff0c;高效…

【数据结构—栈的实现(数组栈)】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、栈 1.1栈的概念及结构 二、栈的实现 2.1头文件的实现—Stack.h 2.2源文件的实现—Stack.c 2.3源文件的测试—test.c 三、栈的实际测试数据展示 3.1正常的出…

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解前言DenseNet讲解Dense Block(稠密块)Dense Layer(稠密层)Transition Layer 过渡层DenseNet模型结构 DenseNet Pytorch代码完整代码附加…

鱼fish数据集VOC+yolo-1400张(labelImg标注)

鱼类&#xff0c;是最古老的脊椎动物。易蓄积重金属。 部分不同染色体数目的杂交的后代依然有生育能力。它们几乎栖居于地球上所有的水生环境&#xff0c;从淡水的湖泊、河流到咸水的大海和大洋。 今天要介绍鱼的数据集。 数据集名称&#xff1a;鱼 fish 数据集格式&#xf…

五分钟快速掌握Maven的核心概念

前两天在一个技术群&#xff0c;有人还在问maven中groupId、artifactId、version这些关键字的含义是什么&#xff0c;于是&#xff0c;我觉得还是很有必要来聊聊Maven中的这些核心概念。 成功不是将来才有的&#xff0c;而是从决定去做的那一刻起&#xff0c;持续累积而成。 …

有基础转Go语言学习笔记(3. 面向对象篇)

有基础转Go语言学习笔记&#xff08;3. 面向对象篇&#xff09; 封装 在Go语言中&#xff0c;封装是通过使用结构体&#xff08;structs&#xff09;和方法&#xff08;methods&#xff09;来实现的。Go语言的封装不同于传统面向对象编程语言中的类&#xff08;class&#xf…

一次持续 15 年的网络安全“攻防之战”

2003 年 7-8 月&#xff0c;冲击波病毒爆发&#xff0c;对网络安全造成严重影响&#xff0c;尤其是校园网。冲击波病毒不仅使得校园网变得卡顿&#xff0c;还会在学生电脑上强制弹出一个倒计时窗口&#xff0c;60 秒后自动关机&#xff0c;给学生正常使用电脑和网络造成了极大不…

JS之递归

递归是什么&#xff1f; 调用自身函数称为递归函数 function fn(){fn()}fn()递归的作用和循环是基本一样的 编写递归函数&#xff0c;一定要包含两个条件 1.基线条件 2.递归条件 接下来我用几个实例为大家带来递归的用法 1.使用递归让延迟器有定时器的效果 function timer() …

Visual Studio Code (Vscode)配置LaTeX

Visual Studio Code (Vscode)配置LaTeX 实操记录 第一步高效检索&#xff0c;找到官方的、靠谱的安装教程&#xff0c;最好多找几个&#xff0c;英文、中文教程都需要 LaTeX WorkshopInstallation and basic settingsHow to install LaTeX (with previews & autocomplete…

Godot导出Android包报错:无效的包名称

问题描述 使用Godot为项目导出Android平台包时报错&#xff0c;提示&#xff1a;“无效的包名称&#xff1a;项目名称不符合包名格式的要求。请显式指定包名。” 解决办法 修改导出配置项“包->唯一名称”。 该项缺省值“org.godotengine.$genname”不能直接使用&#x…

Paper Reading: (ACRST) 基于自适应类再平衡自训练的半监督目标检测

目录 简介工作重点方法CropBankFBRAFFRTwo-stage Pseudo-label Filtering 实验与SOTA比较消融实验 简介 题目&#xff1a;《Semi-Supervised Object Detection with Adaptive Class-Rebalancing Self-Training》&#xff0c;AAAI’22&#xff0c; 基于自适应类再平衡自训练的半…

外汇天眼:心理素质决定交易成败!

在交易市场中&#xff0c;参与者非常多&#xff0c;成功的却极少。 成功的交易者几乎完全凭借个人的聪明才智&#xff0c;迎难而上&#xff0c;依靠顽强的毅力、坚韧不拔的性格以及冒险精神&#xff0c;战胜自己交易路上的一切挫折。 而这其中交易者的心理素质与其盈亏紧密相关…

【复现】vid2vid_zero

问题及解决方法总结。 code&#xff1a;GitHub - baaivision/vid2vid-zero: Zero-Shot Video Editing Using Off-The-Shelf Image Diffusion Models 1.AttributeError: UNet2DConditionModel object has no attribute encoder 据说是预训练模型结构不匹配&#xff0c;偷懒把a…