【网络】简单聊一下 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 main

import (
	"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 main

import (
	"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.mfbz.cn/a/230240.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RPC基础

RPC基础知识 RPC 是什么? RPC(Remote Procedure Call) 即远程过程调用,通过名字我们就能看出 RPC 关注的是远程调用而非本地调用。 为什么要 RPC ? 因为,两个不同的服务器上的服务提供的方法不在一个内存空间&…

使用 Tailwind CSS 完成导航栏效果

使用 Tailwind CSS 完成导航栏效果 本文将向您介绍如何使用 Tailwind CSS 创建一个漂亮的导航栏。通过逐步演示和示例代码,您将学习如何使用 Tailwind CSS 的类来设计和定制导航栏的样式。 准备工作 在开始之前,请确保已经安装了 Tailwind CSS。如果没…

聚观早报 |华为畅享 70正式开售;梦饷科技双12玩法

【聚观365】12月8日消息 华为畅享 70正式开售 梦饷科技双12玩法 华为Mate X5应对火海挑战 谷歌发布AI模型Gemini 字节跳动开启新一轮回购 华为畅享 70正式开售 精致外观与创新科技兼具的华为畅享 70正式开售,1199元起搭载6000mAh超大电池,带来超强…

ModStartBlog v8.7.0 LayUI全新升级,文件顺序选择

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用,支持后台一键快速安装,让开发者能快的实现业务功能开发。 系统完全开源,基于 Apache 2.0 开源协议。 功能特性 丰富的模块市场,后台一键快速安装 …

酿酒生产废水处理的设备需要哪些

酿酒生产废水处理的设备需要以下几种: 1. 格栅:用于去除废水中较大的漂浮物,如酒糟和塑料袋等。 2. 沉淀池或澄清器:进一步去除废水中更小的悬浮物和颗粒物,同时使有机物进行厌氧分解。 3. 过滤器和活性炭吸附装置&…

在阿里云国际上构建共享虚拟主机业务

我们需要3个ECS实例,1个RDS MySQL实例和2个域名。我将使用该域作为我的主域和辅助域。sarathy.infosarathy.site 以下架构图左侧所示的两个 ECS 实例将托管我们的主网站。一个ECS实例用于部署WHMCS,另一个实例用于部署WordPress。WordPress 和 WHMCS 都…

HarmonyOS应用程序框架——UIAbility实操

UIAbility概述 UIAbility是一种包含用户界面的应用组件,主要用于和用户进行交互。UIAbility也是系统调度的单元,为应用提供窗口在其中绘制界面。 每一个UIAbility实例,都对应于一个最近任务列表中的任务。 一个应用可以有一个UIAbility&…

12.Mysql 多表数据横向合并和纵向合并

Mysql 函数参考和扩展&#xff1a;Mysql 常用函数和基础查询、 Mysql 官网 Mysql 语法执行顺序如下&#xff0c;一定要清楚&#xff01;&#xff01;&#xff01;运算符相关&#xff0c;可前往 Mysql 基础语法和执行顺序扩展。 (8) select (9) distinct (11)<columns_name…

poe与chatgpt那个功能更强大

在当前的人工智能领域&#xff0c;Poe Al Chat以其卓越的聊天能力和实用的功能&#xff0c;受到了大家的广泛关注和喜爱。本文好为您个绍Poe Al Chat的功能&#xff0c;以及我们国内用户如何进行充值订阅。Poe Al Chat是一个基于OpenAl的GPT模型开发的人工智能聊天工具。它能够…

有限空间作业中毒窒息事故频发,汉威科技创新方案护航

工贸企业有限空间是我国重大事故多发频发的重点领域之一&#xff0c;安全问题形势严峻。 有限空间是指封闭或者部分封闭、未被设计为固定工作场所&#xff0c;人员可以进入&#xff0c;通风不良&#xff0c;易造成有毒有害物质、易燃易爆气体积聚或者氧含量不足的空间&#xf…

IBM Qiskit量子机器学习速成(四)

量子核机器学习 一般步骤 量子核机器学习的一般步骤如下 定义量子核 我们使用FidelityQuantumKernel类创建量子核&#xff0c;该类需要传入两个参数&#xff1a;特征映射和忠诚度(fidelity)。如果我们不传入忠诚度&#xff0c;该类会自动创建一个忠诚度。 注意各个类所属的…

硕士毕业论文格式修改要点_word

目录 0、最开始要做的事情1、更改样式&#xff08;先善器&#xff09;2、多级标题&#xff08;解决自动更新问题必要的基础设置&#xff09;2、插入图片&#xff08;1&#xff09;设置一个图片样式——“无间隔”&#xff08;2&#xff09;插入题注&#xff08;3&#xff09;修…

上网监控软件——安全与隐私的平衡

网络已经成为人们生活和工作中不可或缺的一部分。然而&#xff0c;随着网络使用的普及&#xff0c;网络安全问题也日益突出。上网监控软件作为网络安全领域的一个重要组成部分&#xff0c;在保护企业和家庭网络安全方面发挥着重要作用。 本文将探讨上网监控软件的背景、功能、优…

泽攸科技桌面型扫描电子显微镜(SEM)技术解析

台式扫描电子显微镜是一种利用电子束扫描样品表面并检测样品反射或发射的电子信号&#xff0c;从而获得样品表面形貌、结构和成分信息的仪器。它的工作原理是由电子枪发出的电子束经过栅极静电聚焦后成为直径50微米的点光源&#xff0c;然后在加速电压作用下&#xff0c;经两三…

普源示波器旋钮数值乱跳, 不更换编码器修复的办法

1: 换电容的办法 直接三个引脚(A/C/B)&#xff0c;A和B&#xff0c;B和C之间并联103电容(10nf),0805封装的焊上正好 2:换编码器 换EC12编码器,柄长15mm,金属柄D口 红框大钮用这个 绿框小钮用这个

案例062:基于微信小程序的健身房私教预约系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

ModuleNotFoundError: No module named ‘dlib‘

解决&#xff1a;ModuleNotFoundError: No module named ‘dlib’ 文章目录 解决&#xff1a;ModuleNotFoundError: No module named dlib背景报错问题报错翻译报错位置代码报错原因解决方法方法一&#xff0c;直接安装方法二&#xff0c;手动下载安装方法三&#xff0c;编译安…

二叉树的层序遍历[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你二叉树的根节点root&#xff0c;返回其节点值的 层序遍历 。&#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],…

如何进行更好的面试回复之缓存函数在项目中的性能优化?

缓存函数是一种提高函数性能的技术&#xff0c;在函数被调用时&#xff0c;会将计算结果缓存起来&#xff0c;以便在后续的调用中直接返回缓存的结果&#xff0c;从而减少了重复计算的时间。 缓存函数的实现通常包括两个步骤&#xff1a; 判断缓存是否存在&#xff1a;在函数被…

华为数通---配置Smart Link主备备份示例

定义 Smart Link&#xff0c;又叫做备份链路。一个Smart Link由两个接口组成&#xff0c;其中一个接口作为另一个的备份。Smart Link常用于双上行组网&#xff0c;提供可靠高效的备份和快速的切换机制。 目的 下游设备连接到上游设备&#xff0c;当使用单上行方式时&…