【TCP】四次挥手(终止连接)

图片

前言

TCP(传输控制协议)是互联网协议(IP)中的一种重要传输层协议,用于在通信的计算机之间建立可靠的、有序的和错误校验的数据传输。在TCP连接中,数据传输是双向的,因此需要一种机制来开始和结束连接。这就是所谓的“握手”和“挥手”。TCP四次挥手是TCP连接断开过程中的一个重要环节,它确保了数据传输的完整性和可靠性。

TCP四次挥手过程和状态变迁

TCP的四次挥手过程发生在两个端点都准备好关闭连接时。以下是四次挥手的详细步骤:

图片

  1. FIN:当一方完成数据发送并决定关闭连接时,它会发送一个FIN报文段,请求关闭连接。此时,发送方进入FIN_WAIT_1状态,等待接收方的确认。

  2. ACK:接收方收到FIN报文段后,会发送一个ACK报文段作为回应,表示同意关闭连接。此时,接收方进入CLOSE_WAIT状态。

  3. FIN:一旦接收方完成所有数据接收并准备关闭连接,它也会发送一个FIN报文段,表示请求关闭连接。此时,发送方进入TIME_WAIT状态。

  4. ACK:接收方发送一个ACK报文段作为回应,确认收到FIN报文段并完成关闭连接。

以下是使用Java代码模拟TCP四次挥手的示例:


import java.io.BufferedReader;  
import java.io.InputStreamReader;  
import java.io.PrintWriter;  
import java.net.Socket;  public class TCPHandshake {  public static void main(String[] args) {  try {  // 创建Socket连接  Socket socket = new Socket("localhost", 8000);  System.out.println("Connected to server");  // 获取输入输出流  BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));  PrintWriter output = new PrintWriter(socket.getOutputStream(), true);  // 第一次挥手:客户端发送FIN报文段请求关闭连接  output.println("FIN");  System.out.println("Sent FIN");  // 等待服务器响应  String response = input.readLine();  System.out.println("Received response: " + response);  // 第二次挥手:服务器发送ACK报文段确认关闭连接请求  output.println("ACK");  System.out.println("Sent ACK");  // 等待客户端响应  response = input.readLine();  System.out.println("Received response: " + response);  // 第三次挥手:客户端发送FIN报文段请求关闭连接  output.println("FIN");  System.out.println("Sent FIN");  // 等待服务器响应  response = input.readLine();  System.out.println("Received response: " + response);  // 第四次挥手:服务器发送ACK报文段确认关闭连接请求  output.println("ACK");  System.out.println("Sent ACK");  // 关闭连接和流  socket.close();  input.close();  output.close();  } catch (Exception e) {  e.printStackTrace();  }  }  
}

第一次挥手:主动关闭方发送关闭请求(FIN)

在TCP的四次挥手过程中,首先由主动关闭方(通常是客户端)发起关闭请求。主动关闭方发送一个TCP报文,其中包含FIN(Finish)标志位,表示主动关闭方不再有数据要发送了。此时,主动关闭方进入FIN_WAIT_1状态,等待被动关闭方的确认。

第二次挥手:被动关闭方回应确认(ACK)

被动关闭方(通常是服务器)接收到主动关闭方的FIN后,发送一个确认(ACK)报文,表示已经收到了关闭请求。此时,被动关闭方进入CLOSE_WAIT状态,表示服务器端的应用程序已经等待关闭了,但仍可以接收来自客户端的数据。

第三次挥手:被动关闭方发送关闭请求(FIN)

在完成自己的数据发送后,被动关闭方也发送一个带有FIN标志的TCP报文,表示被动关闭方也没有数据要发送了。此时,被动关闭方进入LAST_ACK状态,等待主动关闭方的确认。

第四次挥手:主动关闭方回应确认(ACK)

主动关闭方接收到被动关闭方的FIN后,发送一个确认(ACK)报文,表示已经收到了关闭请求。此时,主动关闭方进入TIME_WAIT状态,等待一段时间,以确保被动关闭方收到了确认,并防止可能存在的延迟报文导致连接混乱。一旦等待时间过去,主动关闭方进入CLOSED状态,表示连接已经完全关闭。

为什么挥手需要四次

TCP的四次挥手是为了确保数据流的正确和可靠地关闭。这需要双方都明确地确认关闭请求,并确保所有的数据包都已接收或处理。通过四次握手,每一方都可以确认对方已经完成了数据传输和接收的准备工作。

为什么TIME_WAIT等待的时间是2MSL

TIME_WAIT状态是TCP四次挥手中的一个重要状态,其持续时间通常是2MSL(最大段生存期)。这是为了确保在网络中的所有数据包都已过期并被丢弃,防止出现旧的数据包在网络中循环并导致连接错误关闭的问题。TIME_WAIT状态也提供了一个机会让发送方等待一段时间,以确保接收方已经收到了关闭连接的请求。

等待2MSL的意义

等待2MSL是为了确保在网络中的所有数据包都已过期并被丢弃。如果发送方在发送完最后一个ACK报文段后立即关闭连接,而网络中仍然存在未过期或未被丢弃的数据包,那么这些数据包可能会在网络中循环并导致连接错误关闭。通过等待2MSL的时间,发送方可以确保这些数据包已经过期并被丢弃,从而避免这种情况的发生。此外,等待2MSL的时间也为接收方提供了一个机会,以确保它已经收到了关闭连接的请求并完成了所有必要的处理工作。

如何解决TIME_WAIT状态过多

最好的办法是尽量让客户端主动断开连接,除非遇到一些异常情况,如客户端协议错误、客户端超时等。

打开系统的TIME_WAIT重用和快速回收。

在Linux系统可以修改以下参数:

1.打开TCP对时间戳的支持,保持服务器与客户端时间同步 

net.ipv4.tcp_timestamps=1(默认即为 1)

2.修改net.ipv4.tcp_tw_reuse = 1,允许对处于TIME_WAIT的socket用于建立新的连接

net.ipv4.tcp_tw_reuse = 1 (默认为0)

修改TIME_WAIT连接状态的上限值,超过上限值,处于TIME_WAIT状态的socket将立刻被清除并打印警告信息。

net.ipv4.tcp_max_tw_buckets = 18000,表示系统同时保持处于TIME_WAIT状态的socket的最大数量,默认为18000。

可修改为更小值。

net.ipv4.tcp_max_tw_buckets = 6666

结语

TCP的四次挥手是一个复杂但必要的过程,用于确保可靠地关闭TCP连接。通过四次握手和TIME_WAIT状态,TCP协议可以确保数据流的正确和可靠地关闭,并避免在网络中循环的数据包导致连接错误关闭的问题。了解TCP的四次挥手过程和状态变迁对于理解TCP协议的工作原理和实现可靠的网络通信至关重要。

图片

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

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

相关文章

Mac上新版InfluxDB使用教程

一、简介 官网:influxdb 二、influxdb安装 建议使用Homebrew在 macOS 上安装 InfluxDB v2: brew install influxdb启动influxdb服务:brew services start influxdb 停止influxdb服务:brew services stop influxdb 查看是否启…

docker 运行jar包 指定配置文件

要在Docker中运行JAR包并指定配置文件,你可以创建一个Dockerfile来定义你的容器环境,并在其中指定如何运行JAR包和配置文件。下面是一个简单的例子,展示了如何在Dockerfile中设置这些配置: 第一步:创建 Dockerfile文件…

《MySQL》超详细笔记

目录 基本知识 主流数据库 数据库基本概念 MySQL启动 数据库基本命令 数据库 启动数据库 显示数据库 创建数据库 删除数据库 使用数据库 查询当前数据库信息 显示数据库中的表 导入数据库脚本 表 查看表的结构 查看创建某个表的SQL语句 数据库的查询命令 查询…

人工智能(pytorch)搭建模型24-SKAttention注意力机制模型的搭建与应用场景

大家好,我是微学AI,今天给大家介绍一下人工智能(pytorch)搭建模型24-SKAttention注意力机制模型的搭建与应用场景,本文将介绍关于SKAttention注意力机制模型的搭建,SKAttention机制具有灵活性和通用性,可应用于计算机视…

canvas缩放坐标系(scale)

查看专栏目录 canvas实例应用100专栏,提供canvas的基础知识,高级动画,相关应用扩展等信息。canvas作为html的一部分,是图像图标地图可视化的一个重要的基础,学好了canvas,在其他的一些应用上将会起到非常重…

2024最新版鸿蒙HarmonyOS开发工具安装使用指南

2024最新版鸿蒙HarmonyOS开发工具安装使用指南 By JacksonML 0. 什么是鸿蒙Harmony OS? 华为鸿蒙系统(HUAWEI Harmony OS),是华为公司在2019年8月9日于东莞举行的华为开发者大会(HDC.2019)上正式发布的分…

Java20:新特性

一:Lambda表达式: 1. Lambda表达式使用前后对比: 举类一: Testpublic void test(){ Runnable r1 new Runnable() {Overridepublic void run() {System.out.println("我爱北京天安门!");} };r1.run();Syst…

基于SSM的协同过滤技术的网上书城(有报告)。Javaee项目。ssm项目。

演示视频: 基于SSM的协同过滤技术的网上书城(有报告)。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Sp…

手撕spring bean的加载过程

这里我们采用手撕源码的方式,开始探索spring boot源码中最有意思的部分-bean的生命周期,也可以通过其中的原理理解很多面试以及工作中偶发遇到的问题。 springboot基于约定大于配置的思想对spring进行优化,使得这个框架变得更加轻量化&#…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Radio组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Radio组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Radio组件 单选框,提供相应的用户交互选择项。 子组件 无。 接口 …

第十五篇【传奇开心果系列】Python的OpenCV库技术点案例示例:图像配准

传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例系列短博文目录前言一、常见的图像配准任务介绍二、图像配准任务:图像拼接介绍和示例代码三、图像配准任务:图像校正介绍和示例代码四、图像配准任务:图像配准介绍和示例代码五、基于特征点的配准方法介绍…

面试150 颠倒二进制位 位运算分治 逻辑右移

Problem: 190. 颠倒二进制位 文章目录 思路复杂度位运算分治法 思路 👨‍🏫 参考题解 >>>:逻辑右移(符号位一起移动,高位补零) 复杂度 时间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn) 空间…

Nacos1.X源码解读(待完善)

下载源码 1. 克隆git地址到本地 # 下载nacos源码 git clone https://github.com/alibaba/nacos.git 2. 切换分支到1.4.7, maven编译(3.5.1) 3. 找到启动类com.alibaba.nacos.Nacos 4. 启动VM参数设置单机模式, RUN 启动类 -Dnacos.standalonetrue 5. 启动本地服务注册到本…

3、生成式 AI 如何帮助您改进数据可视化图表

生成式 AI 如何帮助您改进数据可视化图表 使用生成式 AI 加速和增强数据可视化。 图像来源:DALLE 3 5 个关键要点: 数据可视化图表的基本结构使用 Python Altair 构建数据可视化图表使用 GitHub Copilot 加快图表生成速度使用 ChatGPT 为您的图表生成相关内容使用 DALL-E 将…

elementPlus实现动态表格单元格合并span-method方法总结

最近在做PC端需求的时候,需要把首列中相邻的同名称单元格合并。 我看了一下elementPlus官网中的table表格,span-method可以实现单元格合并。 我们先看一下官网的例子: 合并行或列 多行或多列共用一个数据时,可以合并行或列。 …

IDEA生成可执行jar包

1. 进入需要打包的项目,选择 最上方菜单栏的 File → Project Structure 2. 选择 左侧菜单栏 Artifacts → 加号 → JAR → from modules with dependencies 3. 选择入口类 Main Class(点击文件夹图标可以快速选择),点击 OK&#…

go语言每日一练——链表篇(六)

传送门 牛客面试必刷101题—— 判断链表中是否有环 牛客面试必刷101题—— 链表中环的入口结点 题目及解析 题目一 代码 package mainimport . "nc_tools"/** type ListNode struct{* Val int* Next *ListNode* }*//**** param head ListNode类* return bool…

[Python] scikit-learn中数据集模块介绍和使用案例

sklearn.datasets模块介绍 在scikit-learn中,可以使用sklearn.datasets模块中的函数来构建数据集。这个模块提供了用于加载和生成数据集的函数。 API Reference — scikit-learn 1.4.0 documentation 以下是一些常用的sklearn.datasets模块中的函数 load_iris() …

Prompt Engineering实战-构建“哄哄模拟器”

目录 一 背景 二 “哄哄模拟器”的Prompt Prompt 的典型构成 三 操作步骤 3.1 创建对话 3.2 游戏测试 一 背景 前几天《AI 大模型全栈工程师》第二节课讲了“Prompt Engineering,提示工程”,里面提到一些prompt相关的技巧,原则&#xf…

标准库 STM32+EC11编码器+I2C ssd1306多级菜单例程

标准库 STM32EC11编码器I2C ssd1306多级菜单例程 📌原创项目来源于:https://github.com/AdamLoong/Embedded_Menu_Simple📍相关功能演示观看:https://space.bilibili.com/74495335 单片机多级菜单v1.2 👉本次采用的是原…