【网络原理】TCP协议的连接管理机制(三次握手和四次挥手)

news2024/11/24 18:37:41

系列文章目录

【网络通信基础】网络中的常见基本概念

【网络编程】网络编程中的基本概念及Java实现UDP、TCP客户端服务器程序(万字博文)

【网络原理】UDP协议的报文结构 及 校验和字段的错误检测机制(CRC算法、MD5算法)

【网络原理】TCP协议的相关机制(确认应答、超时重传)


文章目录

前言

一、建立连接(三次握手)

建立连接(三次握手)的意义

1)投石问路,确认当前通信路径是否畅通

2)验证通信双方,发送能力和接收能力是否正常

3)三次握手的过程中,通信双方也会协商一些必要的参数

二、断开连接(四次挥手)

三、连接管理过程中涉及到的TCP状态转换


前言

接上文,我们介绍了TCP协议中,保证可靠性传输的核心机制,确认应答和超时重传机制。

TCP协议的连接管理机制,是整个网络原理中,最高频的问题,没有之一!因此,这里单独用一篇博客,详细介绍TCP协议的连接管理机制。

TCP协议的连接管理机制主要包括三次握手建立连接四次挥手断开连接


一、建立连接(三次握手)

在前面的文章中,我们写过TCP回显客户端和服务器程序。

当客户端执行 clientSocket = new Socket(serverIp, serverPort); 这个操作的时候,就是在建立连接。此处只是调用了 socket API,真正连接建立的过程,是由TCP协议完成的。

TCP协议建立连接的这个过程,就称为“三次握手”。

这里谈到的连接,是“虚拟的,抽象的”连接。目的是让通信双方都能保存对方的相关信息。

此处又涉及到六位标志位的其中一位=>SYN,代表同步(synchronize)。所谓的SYN,是一个特殊的,带有SYN标志位的TCP数据包:

  1. 没有载荷,不带有应用层的数据.
  2. 六位标志位的第五位,将该位设置为1.

虽然SYN数据包不带有载荷,但是SYN数据包会包含IP报头(如果在IP网络中传输)或以太网数据帧帧头(如果在以太网中传输),以及TCP报头。这些头部包含了一些必要的信息,比如源IP地址、目标IP地址、源端口、目标端口等。这个过程,也是客户端在告诉服务器,我是谁。

了解了SYN数据包后,再来看下三次握手的大致过程。首先要清楚,客户端是主动的一方,第一次交互,一定有客户端主动发起的:

上图过程中,是有四次交互,简单来说:

  1. 客户端先向服务器发送SYN请求
  2. 服务器回复客户端一个ACK应答报文
  3. 服务器再给客户端发送一个SYN请求
  4. 客户端回复服务器一个ACK应答报文

这个建立连接的过程,本质上就是通信双方各自给对方发起一个SYN,各自给对方回应一个ACK。但实际上,中间的两次交互(2和3),是能够合二为一的。

因为回复一个带ACK标志位的数据包,再回复一个带SYN标志位的数据包,可以合并成一个数据包,这个数据包同时带有ACK标志位和SYN标志位。即第2位(ACK)和第5位(SYN)都为1.

此时这个数据包就同时起到了两个作用,既能应答上个请求,也能发起SYN。

这么做的原因是:网络传输过程中要涉及到多次的封装和分用,两个包合并成一个包,就可以减少一次封装分用的过程,整体的效率就提升了。

经过合并,四次交互也就变成了三次,也就形成了“三次握手”


因此,三次握手的具体过程如下:

  1. 客户端向服务器发送SYN请求: 客户端首先向服务器发送一个带有SYN标志位的数据包,其中包含了客户端的初始序列号(ISN)。

  2. 服务器发送SYN-ACK响应: 服务器收到客户端的SYN请求后,会回复一个带有SYN和ACK标志位的数据包,称为SYN-ACK响应。这个响应中,服务器确认了客户端的SYN请求,并指定了服务器的初始序列号(ISN)。

  3. 客户端发送ACK确认: 最后,客户端收到服务器的SYN-ACK响应后,会发送一个带有ACK标志位的数据包,表示确认了服务器的响应。这个ACK数据包中,客户端会确认收到了服务器的SYN响应,并指定了下一个要发送的序列号。

至此,三次握手完成,TCP连接建立成功,双方可以开始进行数据传输了。

前面给出的都是简图,更适合我们在面试过程中给出,因为更稳,要是画详图,画错了,那就得不偿失了。以下是三次握手的详图:

再通俗地解释一下三次握手的过程:

  1. 客户端向服务器发起建立连接的请求,发送一个SYN,此处的SYN就表示:我想跟你建立连接.
  2. 服务器大概率是会同意请求的(除非客户端太多了,负载极高,服务器无法响应),服务器收到SYN之后,会返回ACK(确认应答),表示收到!同时,服务器还会返回SYN,这个SYN的意思就是,我接受你的连接.
  3. 最后,客户端再给服务器返回一个ACK,表示:我也知道你同意我的请求了.

建立连接(三次握手)的意义

1)投石问路,确认当前通信路径是否畅通

例如地铁,每天早上会空车跑一趟,就是为了验证,这个路线是否畅通,是否存在一些问题。

因此,三次握手,对于可靠传输也是有意义的,但是相对于确认应答以及超时重传,起到的作用就稍逊一筹了。

2)验证通信双方,发送能力和接收能力是否正常

比如,张三和李四要开黑打游戏了。通常,在组队队伍的时候,双方都不知道自己的麦克风和听筒是否能正常工作,都先进行确认,这个过程其实就是三次握手,如下图:

上图中,张三扮演的就是客户端的角色,李四扮演服务器的角色。经过上述过程,张三和李四就够确认各自的麦克风和听筒都能正常工作了。此处,麦克风就对应发送能力,听筒就对应接收能力。

理解了上述图中的过程,我们就能清晰地理解,为什么是三次握手,而不是两次或四次握手:

  • 四次握手显然是可以的,但是没必要。
  • 如果是两次,一定是不行的。因为两次握手,李四(服务器)这边无法确认自己的发送能力是否正常,也无法确认张三(客户端)的接收能力是否正常。

3)三次握手的过程中,通信双方也会协商一些必要的参数

这些参数往往是以“选项”部分来体现的,前面说过,选项的范围是0~40字节。

其中有一个参数是很关键的,即TCP通信的序号:

  • 客户端在发送SYN报文时会包含一个随机生成的序列号(ISN),用于标识客户端发送数据的起始位置。
  • 服务器在回复ACK报文时会确认客户端的序列号,并生成自己的序列号(SSN),用于标识服务器发送数据的起始位置。

这样设计的原因,是为了避免出现一个情况,“前朝的剑,斩本朝的官”。具体过程如下:

  • 第一次连接的过程中,客户端传输的一个数据包,在路上堵车了,迟迟没有发送到对端。
  • 等到到了对端的时候,此时已经不是第一次连接了,而是新的连接了。
  • 此时,这份数据就应该被丢弃。
  • 由于,数据包是按照 IP + 端口号,来识别对端的。
  • 如果恰好出现,两次连接在同一台主机,都是同一个端口号的情况(这种情况是客户端的概率比较低,但服务器概率就比较大了),此时,再要处理这份数据就不合适了。

要解决这一问题,就是通过序号来区分当前数据是否是本次连接的数据。如果是,才进行处理,否则,就丢弃该数据。

二、断开连接(四次挥手)

连接,本质上就是让通信双方保存对方的信息。每个客户端/服务器,都要保存很多的对端信息。

信息一旦多了,就要用到数据结构。断开连接的本质目的,就是把对端的信息,从数据结构中删除/释放掉。

此处谈到的“四次挥手”,指的是谈恋爱中“和平分手”的这种情况。而单方面分手的情况,四次挥手不一定适用,这里会有其他方式来断开连接,因此,不意味着断开连接一定是四次挥手。

此处,又要介绍一个标志位,FIN,FIN => finish(结束)。即六位标志位中的第六位,用于请求关闭连接。

与三次握手不同的是,四次挥手,不一定非得是客户端先发FIN,服务器也可能先发FIN。

  • 调用socket.close(),会触发FIN
  • 进程直接结束,也会触发FIN

四次挥手的过程简图如下(客户端先发起关闭连接请求):

从上图可以看出,四次握手就是通信双方各自给对方发一个FIN,且各自给对方反馈一个ACK。

而且,这里的过程和刚开始的“四次握手”的过程非常相似。那四次挥手能否像三次握手一样,将中间的两次交互(ACK和FIN)合二为一呢?

  • 在标准的TCP四次挥手过程中,ACK和FIN通常是分开发送的。
  • 然而,在某些情况下,确实可能会发生ACK和FIN合并发送的情况,因为在理论上,ACK和FIN可以在同一数据包中发送。这种情况主要依赖于延迟应答和捎带应答机制(后面再说)。

如果实际通信过程中,ACK和第二个FIN时间间隔比较长,此时就无法进行合并了。以下是四次挥手的详图:

三、连接管理过程中涉及到的TCP状态转换

在前面三次握手和四次挥手的详图中,每进行一次握手或挥手,图中都有一个对应的状态。

TCP状态和之前多线程中谈到的“线程”状态,是类似的概念。TCP会根据收到的数据包以及协议规定的状态转换规则来更新连接状态:

  1. 分析收到的数据包: TCP协议栈会分析收到的数据包的头部信息,包括源端口、目标端口、标志位等,以确定数据包所处的状态以及下一步的操作。

  2. 执行状态转换规则: TCP协议定义了一系列状态转换规则,规定了在收到不同类型的数据包时应该如何更新连接状态。根据这些规则,TCP协议栈会根据收到的数据包来进行状态转换。

根据这些状态,TCP就能确定当前应该干什么,对于确保网络通信的可靠性和有效性至关重要。

这个图看起来非常复杂,实际上也真的很复杂,但是只需要关注几个比较重要的状态即可。 

先来看三次握手中比较重要的状态:

客户端还未发起SYN前,服务器处于LISTEN状态,表示服务器这边创建好 serverSocket 了,并且绑定端口号完成(手机开机了,信号良好,随时可以接听电话)

运行之前写的TCP回显服务器程序,通过命令行输入 netstat -ano | findstr 9090  这条命令(在这个命令中,netstat -ano 的作用是显示所有网络连接及其相关的进程ID(PID),而 findstr 9090 则是在输出包含端口号9090的所有进程),查看当前的状态:

ESTABLISHED 已确立的。表示客户端和服务器连接已经建立完毕(有人给我打电话,我接通了,此时我们就可以聊天了)

运行之前写的TCP回显客户端程序(可以运行多次),再次通过这个命令查看当前状态:

此处由于客户端和服务器在同一个机器上运行,因此客户端和服务器都会查出来。

再看四次挥手中比较重要的状态:

谁被动断开连接,谁进入 CLOSE_WAIT 状态。这个状态表示:

  • 接收方已被通知对方不再发送数据,但它仍然可以发送数据给对方。接收方需要执行应用层的关闭操作,并发送一个FIN包来关闭剩余的方向,即关闭对发起方的数据传输。 

CLOSE_WAIT 状态不太容易观察到,代码中会比较快速地关闭socket,这个时候,状态就已经从 CLOSE_WAIT -> LAST_ACK 了。但是如果服务器/客户端出现大量 CLOSE_WAIT  意味着代码可能出现bug了,比如忘记关闭 socket。

谁主动断开连接,谁进入 TIME_WAIT 状态:

  • 表示本端给对端发起FIN之后,对端也给我发FIN了,此时本端进入 TIME_WAIT 状态。这给最后一个ACK的重传留有一定的时间。

TIME_WAIT 状态在Windows上也不太容易观察。它存在的意义,主要是防止最后一个ACK丢失。具体的:

  • 在四次挥手的过程中,会涉及到确认应答和超时重传,如果没有收到ACK就视为丢包,此时就会重传FIN。
  • 进入TIME_WAIT 状态的这一方,如果在重传FIN这个环节,把TCP连接关闭了,保存的对端信息也随之释放了。此时意味着重传FIN的这一方就无法被返回ACK了。

此处 TIME_WAIT 也不是无休止的等待,通常等2MSL(MSL是TCP协议中的一个参数,表示数据段在网络中的最大存活时间,通常以秒为单位。MSL的值取决于具体的实现和环境,但通常为30秒到2分钟之间)

进入TIME_WAIT 状态的这一方等这么长时间,如果对方还没有重传,就说明不会再重传了。同时也确保了对方收到了最后的ACK确认。

至此,TCP协议的连接管理机制就介绍完了,并且前面还介绍了确认应答和超时重传机制,这三个机制都是保证TCP协议可靠传输的重要机制。连接管理机制总结如下:

三次握手(Three-way Handshake):

  1. 第一步(Client -> Server): 客户端发送一个带有SYN标志的数据包给服务器,表示请求建立连接,并选择一个初始序列号(ISN)。
  2. 第二步(Server -> Client): 服务器收到客户端的SYN包后,回复一个带有SYN和ACK标志的数据包给客户端,表示同意建立连接,并确认客户端的ISN,同时选择自己的ISN。
  3. 第三步(Client -> Server): 客户端收到服务器的确认后,再次发送一个带有ACK标志的数据包给服务器,确认服务器的ISN。此时,连接已建立,双方可以开始传输数据。

四次挥手(Four-way Handshake):

  1. 第一步(Client -> Server): 客户端发送一个带有FIN标志的数据包给服务器,表示不再发送数据,但仍可以接收数据。
  2. 第二步(Server -> Client): 服务器收到客户端的FIN包后,回复一个带有ACK标志的数据包给客户端,确认收到了关闭请求。
  3. 第三步(Server -> Client): 服务器发送一个带有FIN标志的数据包给客户端,表示服务器也不再发送数据,但仍可以接收数据。
  4. 第四步(Client -> Server): 客户端收到服务器的关闭请求后,回复一个带有ACK标志的数据包给服务器,确认收到了关闭请求。此时,连接终止。

通过三次握手,客户端和服务器建立起了可靠的连接;而通过四次挥手,双方安全地终止了连接,确保数据的可靠传输。

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

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

相关文章

Linux的FTP服务

目录 1.什么是FTP服务? 2.FTP的工作原理和流程 1 主动模式 2 被动模式 3.搭建和配置FTP服务 1 下载服务包、备份配置文件 2 修改配置文件​编辑 3 匿名访问测试 4 设置黑白命令 1.什么是FTP服务? FTP(file Transfer Protocol&#…

Baidu comate智能编程助手评测

Baidu comate智能编程助手评测 作者:知孤云出岫 目录 一. 关于comate产品 二. 关于comate产品体验 三. 关于实际案例. 四. 关于baidu comate编程助手的实测体验感悟 五. …

(三)登录和注册(handle_auto.go)

登录和注册(handle_auto.go) 文章目录 登录和注册(handle_auto.go)一、所需要的结构体信息二、注册三、登录四、退出 一、所需要的结构体信息 type UserAuth struct{}type LoginReq struct {Username string json:"username" binding:"required"Password …

面试经典150题——求根节点到叶节点数字之和

​ 1. 题目描述 2. 题目分析与解析 2.1 思路一——DFS 理解问题: 首先要理解题目的要求,即对于给定的二叉树,我们需要找出从根节点到所有叶子节点的所有路径,然后将每一条路径上的数字组成一个整数,最后求出这些整数…

【静态分析】静态分析笔记08 - 指针分析 - 上下文敏感

参考: 【课程笔记】南大软件分析课程8——指针分析-上下文敏感(课时11/12) - 简书 ------------------------------------------------------------------------------------------------------------- 1. 上下文不敏感的问题 说明&#…

最详细步骤解决:Apps targeting Android12 and higher are required to specify...

问题原因: 当targetSdkVersion>31时,需要在AndroidManifest.xml中配置android:exported的值,该值为boolean类型。 android:exported解释: activity 是否可由其他应用的组件启动: 如果设为 "true"&#…

python中开发页面的两种方法:Qt Designer(PyQt图形化界面拖拽开发App界面)以及Django(开发Web应用框架)

一、开发独立的窗口,App的那种,可使用tkinter或者PyQt 使用PyQt时,里面有个工具Qt Designer,是一个可视化的界面设计工具,可以通过拖拽等方式来设计界面。下面就是Qt Designer的操作界面: 参考链接如下&am…

Linux——web建立wordpress

下载 [rootnfs-server ~]# yum install php wget https://wordpress.org/latest.tar.gz解压 /var/www/html [rootnfs-server html]# tar -xzvf latest.tar.gz [rootnfs-server html]# rm latest.tar.gz授权 [rootnfs-server html]# chown -R www:www /var/www/html添加文件备…

智能解决装箱问题:使用优化算法实现高效包装

组合优化问题 组合优化(Combinatorial Optimization,CO)数学优化研究的一个分支。主要关注的是从有限的对象集合中寻找最优解的问题。这个词的由来主要是由“组合”和“优化”两部分构成。“组合”指的是从有限的对象集合中选择一部分的过程…

1-内核开发环境ubuntu+virtualbox+mobaXterm搭建

内核开发环境 ubuntuvirtualboxmobaXterm搭建 目录 内核开发环境 ubuntuvirtualboxmobaXterm搭建 1.virtualbox 安装 2.ubuntu 安装 3.网络设置 4.虚拟机安装ssh 服务,更新ubuntu 源安装基本软件 5.mobaXterm 个人免费版本安装 6.总结 本课程教程从0-1开始教…

Druid高性能数据库连接池?SpringBoot整合MyBatis整合SpringMVC整合Druid

文章目录 Druid高性能数据库连接池?SpringBoot整合MyBatis整合SpringMVC整合Druid异常记录spring-boot-starter-parent作用Druid介绍什么是数据库连接池?为什么选择Druid数据库连接池整合SpringBoot,MyBatis,SpringMVC,Druid到Maven项目的真个流程pom文件…

为什么 React 比 Vue 难?你不知道的前端简史!

CSDN里有一个女粉问我,为什么都在说 React 比 Vue 难? 事实上,我不知道这个说法算是客观事实呢,还是“思想钢印”。 但是我第一反应就是盲猜一手,“React 比 Vue 难”这个说法可能源于后端攻城狮的主观评价,因为传统…

华为Pura 70系列,一种关于世界之美的可能

1874年,莫奈创作了《印象日出》的油画,在艺术界掀起了一场革命。当时的主流艺术,是追求细节写实,追求场面宏大的学院派。他们称莫奈等人是“印象派”,认为莫奈的画追求光影表达,追求描绘抽象的意境&#xf…

Oracle正則匹配練習一

1.使用分割符號 select regexp_substr(A_B_C, [^_], 1, 2) FROM DUAL 2.練習2 SELECT SUBSTR(path_string, INSTR(path_string, \, -1, 2) 1, INSTR(path_string, \, -1) - INSTR(path_string, \, -1, 2) - 1) AS extracted_string FROM (SELECT D:\SKY Image\A0-BOTC8…

一个VUE3的页面demo

样子是这样的 目录是这样的 index.vue文件内容 <template><div class"app-container"><div class"content"><div class"form" v-show"showSearch"><el-formref"queryRef":inline"true&qu…

C语言笔试题之找出数组的最大公约数

找出数组的最大公约数 实例要求 1、给定一个整数数组 &#xff0c;返回数组中最大数和最小数的最大公约数&#xff1b;2、两个数的最大公约数是能够被两个数整除的最大正整数&#xff1b;示例&#xff1a; 实例分析 1、要找到数组中最大数和最小数的最大公约数&#xff1b…

Python3.11修改并运行oneforall

遇到的问题 使用python3.11默认无法运行oneforall脚本&#xff0c;出现如下报错 # 解决方案 修改 /usr/local/lib/python3.11/dist-packages/exrex.py exrex.py具体文件路径报错中会显示 vim /usr/local/lib/python3.11/dist-packages/exrex.py# 修改前 from re import sre…

02_c/c++开源库ZeroMQ

1.安装 C库 libzmq sudo apt install libzmq3-dev 实例: https://zeromq.org/get-started/?languagec&librarylibzmq# 编译依赖: pkg-config --cflags --libs libzmq or cat /usr/lib/x86_64-linux-gnu/pkgconfig/libzmq.pc -isystem /usr/include/mit-krb5 -I/usr/in…

Magnet for Mac:高效窗口管理工具

Magnet for Mac是一款专为Mac用户设计的窗口管理工具&#xff0c;旨在帮助用户更高效地管理和布局多个应用程序窗口&#xff0c;提升工作效率。 Magnet for Mac v2.14.0中文免激活版下载 这款软件拥有直观易用的界面和丰富的功能&#xff0c;支持用户将屏幕分割成多个区域&…

低代码将干掉65%软件开发工作:留给码农的时间不多了

IDC预测&#xff0c;到2024年&#xff0c;约有65%的应用软件将通过低代码开发方式实现&#xff0c;同样&#xff0c;Gartner也曾发布过类似的预测&#xff0c;结果与IDC的预测大致相符。 低代码领域的知名公司Mendix之前发布的一份调研报告指出&#xff1a; “在中国&#xf…