“三次握手,四次挥手”这么讲,保证你忘不了

本文通过通俗易懂的农村通话和分手故事,深入解析TCP的三次握手与四次挥手过程,揭示其背后的原理和必要性,帮助读者掌握TCP连接管理的关键知识点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TCP三次握手、四次挥手,在面试这锅滚油里,可谓是炸了千百遍的老油条。

老油条

我们都知道TCP是面向连接的,三次握手就是用来建立连接的,四次挥手就是用来断开连接的。

三次握手

先上图:

三次握手

我们来看一下三次握手的过程:

  • 一开始,客户端和服务端都处于 CLOSED 状态。客户端主动打开连接,服务端被动打卡连接,结束CLOSED z状态,开始监听,进入 LISTEN状态。

一次握手

  • 客户端会随机初始化序号(client_isn),将此序号置于 TCP 首部的「序号」字段中,同时把 SYN 标志位置为 1 ,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态。

二次握手

  • 服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYNACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。

三次握手

  • 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。

好了,经过三次握手的过程,客户端和服务端之间的确定连接正常,接下来进入ESTABLISHED状态,服务端和客户端就可以快乐地通信了。

这里有个动态过程的图示:

三次握手动图

这里有个小细节,第三次握手是可以携带数据的,这是面试常问的点。

那么为什么要三次握手呢?两次不行吗?

  • 为了防止服务器端开启一些无用的连接增加服务器开销
  • 防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

由于网络传输是有延时的(要通过网络光纤和各种中间代理服务器),在传输的过程中,比如客户端发起了 SYN=1 的第一次握手。

如果服务器端就直接创建了这个连接并返回包含 SYN、ACK 和 Seq 等内容的数据包给客户端,这个数据包因为网络传输的原因丢失了,丢失之后客户端就一直没有接收到服务器返回的数据包。

如果没有第三次握手告诉服务器端客户端收的到服务器端传输的数据的话,服务器端是不知道客户端有没有接收到服务器端返回的信息的。服务端就认为这个连接是可用的,端口就一直开着,等到客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。

这样一来,就会有很多无效的连接端口白白地开着,导致资源的浪费。

这个过程可理解为:

非三次握手-有差错情况

还有一种情况是已经失效的客户端发出的请求信息,由于某种原因传输到了服务器端,服务器端以为是客户端发出的有效请求,接收后产生错误。

失效请求

所以我们需要“第三次握手”来确认这个过程:

通过第三次握手的数据告诉服务端,客户端有没有收到服务器“第二次握手”时传过去的数据,以及这个连接的序号是不是有效的。若发送的这个数据是“收到且没有问题”的信息,接收后服务器就正常建立 TCP 连接,否则建立 TCP 连接失败,服务器关闭连接端口。由此减少服务器开销和接收到失效请求发生的错误。

四次挥手

还是先上图:

四次挥手示意图

聚散终有时,TCP 断开连接是通过四次挥手方式。

双方都可以主动断开连接,断开连接后主机中的「资源」将被释放。

上图是客户端主动关闭连接 :

一次挥手

  • 客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。

二次挥手

  • 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。

三次挥手

  • 客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。

四次挥手

  • 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
  • 服务器收到了 ACK 应答报文后,就进入了 CLOSED 状态,至此服务端已经完成连接的关闭。
  • 客户端在经过 2MSL 一段时间后,自动进入 CLOSED 状态,至此客户端也完成连接的关闭。

你可以看到,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手

为什么要挥手四次?

再来回顾下四次挥手双方发 FIN 包的过程,就能理解为什么需要四次了。

  • 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
  • 服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。

从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACKFIN 一般都会分开发送,从而比三次握手导致多了一次。

为什么客户端在TIME-WAIT阶段要等2MSL?

为的是确认服务器端是否收到客户端发出的 ACK 确认报文,当客户端发出最后的 ACK 确认报文时,并不能确定服务器端能够收到该段报文。

所以客户端在发送完 ACK 确认报文之后,会设置一个时长为 2MSL 的计时器。

MSL 指的是 Maximum Segment Lifetime:一段 TCP 报文在传输过程中的最大生命周期。

2MSL 即是服务器端发出为 FIN 报文和客户端发出的 ACK 确认报文所能保持有效的最大时长。

服务器端在 1MSL 内没有收到客户端发出的 ACK 确认报文,就会再次向客户端发出 FIN 报文:

  • 如果客户端在 2MSL 内,再次收到了来自服务器端的 FIN 报文,说明服务器端由于各种原因没有接收到客户端发出的 ACK 确认报文。

客户端再次向服务器端发出 ACK 确认报文,计时器重置,重新开始 2MSL 的计时。

  • 否则客户端在 2MSL 内没有再次收到来自服务器端的 FIN 报文,说明服务器端正常接收了 ACK 确认报文,客户端可以进入 CLOSED 阶段,完成“四次挥手”。

所以,客户端要经历时长为 2SML 的 TIME-WAIT 阶段;这也是为什么客户端比服务器端晚进入 CLOSED 阶段的原因。

这里同样有个动态过程的图示:

四次挥手动态图示

好了,我们的文章到这就……

唉,不对,就这么完了,这会我好像知道了,但过会儿那就说不定了。

知识不进脑子

没关系,我苦思冥想,找了两个大白话的例子,保准你忘不了。

大白话说三次握手

在二十年前的农村,电话没有普及,手机就更不用说了,所以,通信基本靠吼。

老张和老王是邻居,这天老张下地了,结果家里有事,热心的邻居老王赶紧跑到村口,开始叫唤老王。

  • 老王:老张唉!我是老王,你能听到吗?
  • 老张一听,是老王的声音:老王老王,我是老张,我能听到,你能听到吗?
  • 老王一听,嗯,没错,是老张:老张,我听到了,我有事要跟你说。

“你老婆要生了,赶紧回家吧!”

老张风风火火地赶回家,老婆顺利地生了个带把的大胖小子。

握手的故事充满了幸福和美满。

大白话说三次握手

大白话说四次挥手

假如博主有一个女朋友——只是“假如”,该死的,这不争气的眼泪,怎么止不住地滴在键盘上。

由于博主上班九九六,下班肝博客,导致没有时间陪女朋友,女朋友忍无可忍。

  • 女朋友:臭男人,最近你都不理我,你是不是不爱我了?你是不是外面有别的狗子了?我要和你分手?
  • 沙雕博主一愣,怒火攻心:分手就分手,不陪你闹了,等我把东西收拾收拾。

沙雕博主小心翼翼地装起了自己的青轴机械键盘。

  • 哼,蠢女人,我已经收拾完了,我先滚为敬,再见!
  • 女朋友:滚,滚的远远的,越远越好,我一辈子都不想再见到你。

唉,挥手的故事总充满了悲伤和遗憾!

白话四次挥手


好了,白话纯属娱乐!看在博主费了不少脑子的份上,点个赞再走呗!!




参考:

【1】:两张动图-彻底明白TCP的三次握手与四次挥手

【2】:35 张图解:被问千百遍的 TCP 三次握手和四次挥手面试题

【3】:三次握手+四次挥手,一文搞定所有!

<think>我们正在讨论UDP协议下的通信逻辑连接问题。根据用户提供的引用和之前的问题,我们需要明确UDP协议是否需要在每次通信时建立逻辑连接。 首先,从引用[1]和[2]中我们可以知道: - UDP是无连接的协议,即在发送数据之前需要建立连接。 - 而TCP是面向连接的,需要先建立连接(三次握手)才能通信。 因此,UDP协议在通信时需要建立逻辑连接。每次发送数据都是独立的,需要预先建立连接,也会在发送后维护连接状态。 所以,对于UDP协议来说: - 没有“逻辑连接建立”这一步骤。 - 每次通信(即每个数据报的发送)都是独立的,需要依赖之前的通信状态。 结论:在UDP协议下,两个设备进行通信时,既需要在第一次通信时建立逻辑连接,更需要每次通信都建立。每次发送数据报都是独立的操作。 但是,我们需要注意,虽然UDP本身是无连接的,但在应用层上,我们可以通过设计实现类似“连接”的概念(例如在应用层维护会话状态)。过,这已经超出了UDP协议本身的范畴。 下面我们根据引用内容具体分析: 引用[1]明确说明:UDP是无连接通信协议,发送端和接收端建立逻辑连接。 引用[2]指出:UDP是无连接的,发送数据之前需要建立连接。 引用[3]提到:Socket套接字是IP地址和端口号的组合,网络通信是Socket间的通信,但UDP的Socket通信是无连接的。 引用[4]展示了UDP接收数据的Java代码,其中并没有建立连接的过程,而是直接创建DatagramSocket并接收数据包(receive方法是阻塞的,但并没有连接建立的过程)。 引用[5]描述的是TCP的确认机制和断开连接(四次挥手),与UDP无关。 因此,回答用户的问题:UDP协议下,每次通信都需要建立逻辑连接。 为了更清晰地说明,我们可以对比TCP和UDP: TCP通信流程(需要建立连接): 1. 三次握手建立连接 2. 传输数据(可能有多轮) 3. 四次挥手断开连接 UDP通信流程(无连接): 1. 发送端:构造数据报,指定目标地址和端口,发送。 2. 接收端:监听某个端口,接收到数据报后处理。 每次UDP通信(每个数据报)都是独立的,即使连续发送两个数据报到同一个目的地,它们之间也没有任何关联。 所以,回答如下:</think>### UDP协议下逻辑连接的建立机制 根据引用内容,UDP协议**需要建立任何逻辑连接**,无论是首次通信还是后续通信。以下是关键分析: #### 一、UDP的无连接特性 1. **本质差异** UDP是**无连接协议**(Connectionless Protocol),与TCP的面向连接机制根本同: - TCP要求通信前必须通过三次握手建立逻辑连接[^2][^5] - UDP直接发送数据包,**无连接建立过程**[^1][^2] 2. **通信流程对比** ```mermaid graph LR subgraph TCP协议 A[三次握手建立连接] --> B[数据传输] B --> C[四次挥手断开连接] end subgraph UDP协议 D[直接发送数据包] --> E[接收端处理数据] E --> F[无连接状态维护] end ``` 3. **核心特征** - **无连接建立**:每次发送数据包都是独立操作,无预握手过程[^1] - **无状态维护**:通信双方记录连接状态[^3] - **无确认机制**:发送后等待接收方确认[^2][^5] - **无断开流程**:通信结束无需挥手断开[^2] #### 二、UDP通信的实际操作 1. **发送方操作**(引用[4]代码解析) ```java // 创建Socket(指定目标) DatagramSocket socket = new DatagramSocket(); // 构造数据包(包含目标地址) DatagramPacket packet = new DatagramPacket(data, data.length, address, port); // 直接发送(无连接建立) socket.send(packet); ``` **关键点**:每次发送都需显式指定目标地址,无持久连接概念。 2. **接收方操作** ```java // 绑定端口监听(无连接等待) DatagramSocket ds = new DatagramSocket(8888); // 准备空缓冲区 byte[] buffer = new byte[1024]; DatagramPacket dp = new DatagramPacket(buffer, buffer.length); // 阻塞接收数据(来自任意源) ds.receive(dp); // 引用[4] ``` **关键点**:接收方区分通信对象,处理所有到达指定端口的数据。 #### 三、与TCP协议的对比 | **特性** | UDP协议 | TCP协议 | |------------------|---------------------------------|---------------------------------| | 连接建立 | **无需建立** | 必须三次握手[^2][^5] | | 数据传输单位 | 报文(Datagram) | 字节流(Byte Stream) | | 可靠性 | 保证到达/顺序[^1][^2] | 可靠传输(确认重传机制)[^5] | | 资源消耗 | 低(首部仅8字节)[^2] | 高(首部20字节+连接维护)[^2] | | 适用场景 | 实时视频/音频/广播[^1][^2] | 网页/邮件/文件传输[^2] | #### 四、应用层模拟连接 虽然UDP本身无连接,但**应用层可模拟连接状态**: 1. **会话标识**:在数据包中添加会话ID(如QUIC协议) 2. **状态跟踪**:应用维护通信状态(如序列号校验) 3. **保活机制**:周期性发送心跳包维持"虚拟连接" > 💡 注意:这些是**应用层行为**,改变UDP协议的无连接本质[^3]。 --- ### 结论 在UDP协议下: ✅ **无需在第一次通信时建立逻辑连接** ✅ **每次通信都是独立的无连接操作** ✅ **通信管道概念适用于UDP** UDP的通信模式本质上是"**发后即忘**"(Fire-and-Forget),每个数据包都是自包含的独立传输单元[^1][^2][^3]。 ---
评论 64
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三分恶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值