【网络原理3】TCP连接管理

news2024/12/26 14:28:08

        TCP这种传输层协议必须是有连接的。连接管理,就是TCP当中管理如何建立连接、如何断开连接的方式。

目录

TCP建立连接的方式(三次握手)

合并两次连接之后变成"三次握手"

站在具体发送什么报文的视角,理解三次握手 

 发送报文之前

第一步:客户端主动向服务端发送(第一次握手)

第二步:服务端主动向客户端发送(第二次握手)

第三步:客户端主动向服务端发送(第三次握手)

第四步:三次握手建立连接完成之后

为什么三次握手必须是三次,不可以是四次

四次握手可以合并成三次的原因:

三次握手,为什么不可以是两次

 总结一下:三次握手的作用(两个)

TCP四次挥手

四次挥手,为什么不可以像三次握手一样合并中间两次握手

第一步:客户端主动发起FIN:

第二步:服务端主动发送ack

第三步:服务端主动发送FIN

第四步:客户端收到FIN之后,再次发送ack 

 第二、第三次握手为什么不可以合并

 四次挥手当中涉及到的两个重要的TCP状态

服务端出现大量的close_wait状态是什么原因


TCP建立连接的方式(三次握手)

通信双方需要彼此记录对方的信息,彼此之间需要"相互认同"。

下面,通过一个故事,来理解一下"三次握手"。

所谓建立连接,一定是客户端服务端之间建立连接


一天,小明去对小红表白(建立连接);

发生了以下的场景:

时间轴小明(客户端)小红(服务端)
t1小红小红,你可以成为我npy吗?
t2好啊好啊
t3小明小明,你可以成为我npy吗?
t4好啊好啊

       以上场景,每通话一次,相当于一次"握手"。在通话完成之后,小明与小红就正式成为NPY,也就是建立连接。

        我们都说,TCP是通过三次握手建立连接的。但是,在上述的场景当中,可以看到:出现了4次"握手",本质上也就是4次交互。但是,为什么又说是"三次"呢?


合并两次连接之后变成"三次握手"

       可以看到,在t2,t3两个时刻,小红发出了两次消息,如果把这两次消息合并成为1次。这样,4次握手,就变成了三次握手了。 


 合并之后的握手情况:

下面是具体的读取情况:

时间轴小明小红
t1小红小红,你可以成为我npy吗?
t2好啊好啊,你可以成为我的npy吗?
t3好啊好啊

站在具体发送什么报文的视角,理解三次握手 

 发送报文之前

客户端客户端状态服务端服务端状态报文类型备注(其他)
CLOSELISTEN   

       LISTEN的含义:(相当于手机开机,信号良好)

       ①表示服务端已经准备就绪,随时可以等待客户端来建立连接了。


        ②这个状态为服务端专有的状态,含义是"监听"用于服务端监听某一个端口的状态;

    


第一步:客户端主动向服务端发送(第一次握手)

客户端客户端状态服务端服务端状态报文类型备注(其他)
主动发送SYN_SEND   syn

       同步报文段(syn标志位为1);

       客户端发送了syn报文之后,客户端进入了syn_send的状,等待服务端确认


第二步:服务端主动向客户端发送(第二次握手)

客户端客户端状态服务端服务端状态报文类型备注(其他)
主动发送SYN_RECVsyn+ack

 同步报文段(syn标志位为1) 

 应答报文段(ack标志位为1)

 syn和ack都属于内核态发送的文

服务端发送之后进入SYN_RECV状态


第三步:客户端主动向服务端发送(第三次握手)

客户端客户端状态服务端服务端状态报文类型备注(其他)
主动发送进入步骤4的状态进入步骤4的状态ack

        应答报文段(ack标志位为1)

        此报文可以携带数据,但是前两次不可以携带数据。


第四步:三次握手建立连接完成之后

客户端客户端状态服务端服务端状态报文类型备注(其他)
ESTABLISHEDESTABLISHED   

       此状态为客户端与服务端均可以有的状态,表示客户端与服务端已经经过三次握手建立好了连接


        读音: [ɪˈstæblɪʃt] 

 所以,综上所述,客户端与服务端之间三次握手的流程图大致为下面这样:

  


为什么三次握手必须是三次,不可以是四次

在上述的通信过程当中,每发送一次报文,就相当于封装、分用一次。

关于什么是封装、分用,也已经在这一篇文章当中提到了。

初识网络:IP、端口、网络协议、TCP-IP五层模型_革凡成圣211的博客-CSDN博客TCP/IP五层协议详解https://blog.csdn.net/weixin_56738054/article/details/128666970?spm=1001.2014.3001.5501简而言之:

封装就发送方把报文从应用层报文-->数据链路层进行的一个封装;

分用就是接收方把报文从数据链路层--->应用层的一个过程;

       而每封装、分用一次,都是需要开销的;因此,在确保发送方、接收方都可以确保双方可以接收消息的情况下,应当尽可能地减少封装、分用的次数。也就从4次握手削减为了三次;

       也就是合并了接收方回复发送方的那一次发送报文。

图解一下:三次握手:


四次握手可以合并成三次的原因:

原因1:

       三次握手的过程,是在操作系统内核当中完成的,也就是三次握手发生在内核态,应用程序无法干涉;

      也就是在第二次握手的时候,服务端的系统收到syn之后,就会立即发送ack给客户端。

      ack的发送与接收,都属于内核态的工作。

      因为握手的过程都发生在内核态,因此可以合并中间两次握手。

原因2:

      多一次握手,就会多一次分装分用的过程。每封装分用一次,都是需要比较大的开销的。


三次握手,为什么不可以是两次

如果变成了两次,就会出现下面的结果(图解)

给定下面一个场景:假设小明和小红连麦打游戏,他们之间需要彼此确认双方的话筒和耳机是否正常;

时间轴小明小红
t1小红小红,你听到我说话了嘛?
t2小明小明,我听到你说话啦

       可以看到,t1时刻,小明向小红发送了一个语音。然后小红听到了小明的语音之后(t2时刻),说明了两个事实:

 事实1:小明(发送方)语音(发送功能)正常;

 事实2:小红(接收方)耳机(接收功能)正常;

也就是说:作为发送方,它可以正常发送消息;作为接收方,它可以正常接收消息

    但是,却无法验证另外两个事实,那就是:

     事实3:小红(接收方)语音(发送功能)是否正常;

     事实4:小明(发送方)耳机(接收功能)是否正常;


 总结一下:三次握手的作用(两个)

  作用1:确保了发送方与接收方通信上面的彼此认同;

  作用2:验证了发送方与接收方的发送和接收能力是否正常;

需要注意的是:

  TCP的可靠性和有无连接没有关系

  可靠性是依靠确认应答机制(ack)+超时重传机制来保证的。

  而建立连接是依靠三次握手机制来完成发送方接收方之间的自检


TCP四次挥手

三次握手,是建立连接的过程。四次挥手,是断开连接的过程。

经过了四次挥手之后,客户端与服务端之间就断开连接了。

下面,通过一个场景,模拟四次挥手的过程:

假设小明想跟小红提出分手:

时间轴小明(客户端)小红(服务端)
t1小红小红,我们分手吧
t2好啊好啊
t3小明,我们分手吧
t4好啊好啊

       经历了以上的四次挥手之后,小明和小红就"成功分手了",也就相当于客户端与服务端主动断开连接了。


四次挥手,为什么不可以像三次握手一样合并中间两次握手

下面,站在具体发送报文的角度,理解一下四次挥手:

首先,需要了解一个前提条件:

当报文段的ack标志位为1的时候,这个报文的发送和接收都工作在内核态;

当报文段的FIN标志位为1的时候,这个报文段的发送和接收都工作在用户态;

在发起四次挥手之前,客户端和服务端都在建立连接时候的状态(ESTABLISHED) 

第一步:客户端主动发起FIN:

客户端客户端状态服务端服务端状态报文类型备注(其他)
主动发送FIN_WAIT1FIN

①发送报文的FIN标志位为1

FIN报文段的发送与接收,都发生在用户态

③客户端发送了FIN之后进入FIN_WAIT1状态


第二步:服务端主动发送ack

客户端客户端状态服务端服务端状态报文类型备注(其他)
主动发送CLOSE_WAITack

①发送报文的ack标志位为1。

②ack报文段的发送发生在内核态

③服务端发送了第一次ack之后之后进入了CLOSE_WAIT状态


第三步:服务端主动发送FIN

客户端客户端状态服务端服务端状态报文类型备注(其他)
主动发送LAST_ACKFIN

①发送报文的FIN标志位为1

FIN报文段的发送与接收,都发生在用户态

③服务端发送了FIN之后,进入了LAST_ACK状态


第四步:客户端收到FIN之后,再次发送ack 

客户端客户端状态服务端服务端状态报文类型备注(其他)
主动发送TIME_WAITack

客户端发送的ack标志位为1。

发送的过程发生在内核态。


客户端发送了最后一次ack之后,自身进入了TIME_WAIT状态

ps :经过了第四步之后,客户端进入了TIME_WAIT状态,服务端在收到了ack之后,立刻进入了close状态。客户端在TIME_WAIT状态持续2MSL之后,也进入了TIME_WAIT状态。


 第二、第三次握手为什么不可以合并

       FIN的发起,不是由内核控制的,而是由应用程序发起的。当调用socket的close方法(或者进程退出)才会触发FIN。

       ACK则是由内核控制的,是在收到客户端发送的FIN之后,立即返回ACK。

      由于FIN和ACK一个工作在用户态,另外一个工作在内核态,因此不可以合并。

       但是,在特殊情况下面,也有可能合并。

       回到这一篇文章当中,实现一个简单的TCP。
(1条消息) 实现一个TCP客户端——服务端协议_革凡成圣211的博客-CSDN博客_tcp客户端实现https://blog.csdn.net/weixin_56738054/article/details/128750183?spm=1001.2014.3001.5501      

挥手次数发起方发送报文类型说明
1客户端FIN        服务端的 scanner.hasNext()读取到的值为false,因为内核收到了客户端发送的FIN数据报。(第一次挥手)
2

服务端

ack

        在读取到scanner.hasNext()的值为false的时候,立即返回ack报文。

        步骤2在内核当中完成

3

服务端

FIN        应用程序finally代码块当中调用close方法,相当于发送FIN给客户端
4客户端ack        客户端在收到了步骤3发送的FIN之后,立刻在内核当中发送ack给服务端

        关于第二次挥手和第三次挥手,如果它们之间间隔的时间比较短,那么救有可能被合并成为一次。


 图解一下:客户端与服务端的发送与接收过程:下图来源于《小林coding》

  


 四次挥手当中涉及到的两个重要的TCP状态

状态的名称状态发生的场景(假定是客户端主动断开连接,服务端被客户端断开连接)说明出现在哪一方
CLOSE_WAIT

如果客户端TCP主动断开服务端TCP连接,那么服务端TCP的状态就是CLOSE_WAIT,其实就是等待关闭

等待关闭:(等待调用close方法关闭连接)被断开连接的一方
TIME_WAIT

       四次挥手结束之后,客户端进入的状态;

       此时,这里的TIME_WAIT要保持当前的TCP连接状态不要立即释放,原因:

       最后一个ack刚刚发出去的时候,防止丢失的情况。

       等待一段时间之后,如果接收方(服务端)没有收到重传的FIN。

       那么就会再由服务端发送一次FIN;         

        TIME_WAIT就是为了服务端重新发送一次ack而设定的。


       TIMEWAIT最大时间:2MSL,也就是如果服务端隔了2MSL没有发送给客户端,那么就会由服务端再次发送一次FIN

       

     出现在主动断开连接的一方;

服务端出现大量的close_wait状态是什么原因

说明服务端的程序没有调用 close 函数关闭连接,也就是说,服务端没有发送FIN报文段。

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

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

相关文章

Git - 在主分支上创建分支并提交代码

拉取最新代码 因为当前在 master 分支下,你必须拉取最新代码,保证当前代码与线上同步(最新),执行以下命令: git pull origin master创建分支 目前我们在 master 主分支上,需要执行以下命令&…

【Unity】[入门tips与通用性原则] 一些经验技巧和更好地写出简洁易懂的程序的原则方法

本文将持续间断更新 本文主要面向初级程序员,为了方便Unity开发,有些快捷键的方式和一些通用性的技巧tips等会在这篇博客内持续更新,欢迎点赞收藏 快捷键 Ctrl S ; 快捷保存!闲着没事就来两下!CtrlShif…

CMake基础使用和实战详解

CMake基础使用和实战详解一、CMake简介1.1、cmake 的特点1.2、注意1.3、使用建议二、安装 cmake三、CMake的简单使用3.1、准备工作3.2、开始构建3.3、解释CMakeLists.txt的内容3.4、基本语法规则四、更像样的CMake工程4.1、准备工作4.2、构建4.3、语法解释4.4、修改保存目标二进…

水文监测场景的数据通信规约解析和落地实践

[小 迪 导 读]:江苏云上需要通过云平台接入水文设备来实现水文数据的采集、存储、显示、控制、报警及传输等综合功能。企业介绍江苏云上智联物联科技有限公司是专业从事物联网相关产品与解决方案服务的高科技公司,总部位于美丽的江苏无锡。公司遵循“智联…

linux高级命令之死锁

死锁学习目标能够知道产生死锁的原因1. 死锁的概念死锁: 一直等待对方释放锁的情景就是死锁为了更好的理解死锁,来看一个现实生活的效果图:说明:现实社会中,男女双方一直等待对方先道歉的这种行为就好比是死锁。死锁的结果会造成应用程序的停止响应&…

面试官:你是怎样理解Fiber的

hello,这里是潇晨,今天我们来聊一聊Fiber。不知道大家面试的时候有没有遇到过和react Fiber相关的问题呢,这一类问题比较开放,但也是考察对react源码理解深度的问题,如果面试高级前端岗,恰巧你平时用的是re…

细谈JavaWeb中的Request和Response

文章目录1,Request和Response的概述2,Request对象2.1 Request继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数的通用方式2.4 请求参数中文乱码问题2.4.1 POST请求解决方案2.4.2 GET请求…

MySQL使用C语言连接

文章目录MySQL使用C语言连接引入库下载库文件在项目中使用库使用库连接数据库下发SQL请求获取查询结果MySQL使用C语言连接 引入库 要使用C语言连接MySQL,需要使用MySQL官网提供的库。 下载库文件 下载库文件 首先,进入MySQL官网,选择DEVEL…

Java代码使用最小二乘法实现线性回归预测

最小二乘法简介最小二乘法是一种在误差估计、不确定度、系统辨识及预测、预报等数据处理诸多学科领域得到广泛应用的数学工具。它通过最小化误差(真实目标对象与拟合目标对象的差)的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数…

如何写一个 things3 client

Things3[1] 是一款苹果生态内的任务管理软件,是一家德国公司做的,非常好用。我前后尝试了众多任务管理软件,最终选定 things3,以后有机会会写文章介绍我是如何用 things3 来管理我的日常任务。本文主要介绍欧神写的 tli[2] 工具来…

3D沉浸式体验开发技巧【Three.js】

在本文中,我们将看看如何使用 Three.js 创建一个充满后期效果和微交互的迷你城市。 推荐:将 NSDT场景编辑器 加入你的3D开发工具链。 1、背景介绍 我是一个游戏爱好者。 我一直梦想创建一个交互式迷你城市,使用饱和的颜色,类似于…

Android自动化测试(UiAutomator)——UiObject

本文主要讲解使用UiAutomator的一些技巧,希望对于初学者有一定的帮助 UiObject 1、首先要声明对象 UiObject XXX new UiObject(new Selector) ; 2、其次对对象进行操作 操作类型包括: 执行类:文本输入与清除、点击/长按、拖动/滑动、 …

JAVA JDK 常用工具类和工具方法

目录 Pair与Triple Lists.partition-将一个大集合分成若干 List集合操作的轮子 对象工具Objects 与ObjectUtils 字符串工具 MapUtils Assert断言 switch语句 三目表达式 IOUtils MultiValueMap MultiMap JAVA各个时间类型的转换(LocalDate与Date类型&a…

开源软件AirByte:入湖入仓,数据集成管道

从ETL到ELT就传统的 ETL而言,当我们开始构建数据仓库时,都要先去了解业务流程,明晰业务是如何运转的,数据是如何留痕的。通过收集用户的相关需求,从而去规划设计报表。企业需要进行数仓分域、分层、逻辑建模等一系列操…

Linux下程序调试的方法【GDB】GDB相关命令和基础操作(命令收藏)

目录 1、编译 2、启动gdb调试 2.1 直接运行 2.2 运行gdb后使用run命令 2.3 调试已运行的程序 3、图形界面提示 4、调试命令 1、查看源码 2、运⾏程序/查看运⾏信息 3、设置断点 5、单步/跳步执⾏ 6、分割窗口 7、其他命令 8、相关参数 1、编译 在编译时要加上-g选…

stm32f407探索者开发板(十七)——串口寄存器库函数配置方法

文章目录一、STM32串口常用寄存器和库函数1.1 常用的串口寄存器1.2 串口相关的库函数1.3 状态寄存器(USART_ SR)1.4 数据寄存器(USART_ DR)1.5 波特率寄存器(USART_BRR)二、串口配置一般步骤一、STM32串口常…

java static关键字 万字详解

目录 一、为什么需要static关键字: 二、static关键字概述 : 1.作用 : 2.使用 : 三、static修饰成员变量详解 : 1.特点 : 2.细节 : ①什么时候考虑使用static关键字? ②静态变量和非静态变量的区别? ③关于静态变量的初始化问题 : ④关于静态变…

基于springboot+vue的器官捐献系统

基于springbootvue的器官捐献系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍&…

内网渗透(四十一)之横向移动篇-PsExec工具远程命令执行横向移动

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…

CCNP350-401学习笔记(201-250题)

201、An engineer attempts to configure a trunk between switch SW1 and switch SW2 using DTP, but the trunk does not form. Which command should the engineer apply to switch SW2 to resolve this issue? A. switchport mode dynamic desirable B. switchport mode a…