三次握手四次挥手(对话场景)

一、先搞懂背景:TCP 是个什么东西?

TCP 是一个可靠的、面向连接的协议。

  • 就像打电话:你和对方都要先 "喂?听得见吗?" 确认线路没问题,再开始说话,说完还要互相确认 "我挂了",避免对方还在等。
  • 三次握手就是建立连接的过程 ,四次挥手就是断开连接的过程。

二、三次握手:建立连接(为什么是三次,不是两次?)

核心目标

让客户端和服务器,互相确认三件事:

  1. 我的发送能力没问题
  2. 我的接收能力没问题
  3. 对方的发送和接收能力也没问题

角色分工

  • 客户端:主动发起连接的一方(比如你的浏览器)
  • 服务器:被动等待连接的一方(比如网站的服务器)

三次握手的完整流程(带对话场景)

假设客户端叫 A,服务器叫 B。

第一次握手:A → B(SYN)

A 给 B 打电话:

"喂,B 吗?我是 A,我想跟你连个线,我的初始序号是 x,你能听到我说话吗?"

  • 对应报文:SYN=1,seq=x
  • 服务器收到后:知道了 "A 的发送能力没问题,B 的接收能力也没问题",但 B 还不知道 A 能不能听到自己说话。
第二次握手:B → A(SYN+ACK)

B 给 A 回电话:

"我听到你了 A!你的序号 x 我收到了,我确认收到你的请求(ACK=x+1)。我也想跟你连线,我的初始序号是 y,你能听到我说话吗?"

  • 对应报文:SYN=1,ACK=1,ack=x+1,seq=y
  • 客户端收到后:知道了 "B 的发送和接收能力都没问题,A 的接收能力也没问题"。
第三次握手:A → B(ACK)

A 再回 B 一句:

"收到你的回应啦!我也听到你说话了,确认你的序号 y(ACK=y+1),我们可以开始传数据了!"

  • 对应报文:ACK=1,ack=y+1
  • 服务器收到后:终于确认 "A 的接收能力没问题",双方正式建立连接。

为什么不能两次握手?

如果只有两次,B 发完第二次握手的包后,就以为连接建立成功了,开始给 A 发数据。但如果 A 没收到这个包,A 根本不知道 B 要连,就会忽略 B 的数据,B 这边就会一直等 A 回应,白白浪费资源。三次握手就是为了双向确认双方都收到了对方的信号,避免这种 "单向确认" 的问题。


三、四次挥手:断开连接(为什么是四次?)

TCP 是全双工的,意思是:A 和 B 可以同时互相发数据,像双向车道。断开连接时,两边都要确认自己这边的 "车道" 关了,所以需要四次挥手。

核心目标

双方都确认:

  1. 对方不会再给我发数据了
  2. 我这边也发完了,可以安全断开了

四次挥手的完整流程(带对话场景)

还是 A(客户端)和 B(服务器)。

第一次挥手:A → B(FIN)

A 说:

"B,我这边的数据发完了,我不想再给你发数据了,我准备关我的发送通道了(FIN),你收到了吗?"

  • 对应报文:FIN=1,seq=u
  • B 收到后:知道 A 不会再发数据了,但 B 可能还有数据没发给 A,所以 B 先回个确认,不马上关自己的通道。
第二次挥手:B → A(ACK)

B 回 A:

"收到了,我知道你不发数据了,我先确认一下(ACK=u+1),我这边还有点数据要发给你,等我发完再跟你说。"

  • 对应报文:ACK=1,ack=u+1
  • 此时,A 到 B 的方向(A 的发送通道)关闭了,但 B 到 A 的方向还能继续传数据。
第三次挥手:B → A(FIN)

B 把剩下的数据发完了,跟 A 说:

"A,我这边的数据也发完了,我也不想再给你发数据了,我准备关我的发送通道了(FIN),你收到了吗?"

  • 对应报文:FIN=1,ACK=1,seq=v,ack=u+1
  • A 收到后,知道 B 也发完了,准备回个确认。
第四次挥手:A → B(ACK)

A 回 B:

"收到了,我知道你不发数据了,确认一下(ACK=v+1),你可以关了。"

  • 对应报文:ACK=1,ack=v+1
  • 服务器收到后,立刻关闭连接。客户端这边会等一段时间(TIME_WAIT),确保 B 收到了这个确认,避免 B 没收到,一直等不到回应。

为什么挥手是四次,握手却是三次?

因为握手的时候,B 可以把 "确认 A 的请求" 和 "向 A 发起连接请求" 合并成一个包(SYN+ACK),所以两次合并成了一次,总共三次。但挥手的时候,B 收到 A 的 FIN 后,可能还有数据没发完,不能马上回 FIN,必须先回 ACK 确认,等数据发完了再发 FIN,所以 ACK 和 FIN 必须分成两次发,总共四次。


四、关键补充:几个容易搞混的点

  1. SYN、ACK、FIN 是什么?
    • SYN:同步位,用来发起连接请求
    • ACK:确认位,用来告诉对方 "我收到你的包了"
    • FIN:结束位,用来发起断开请求
  2. 序号 seq 和确认号 ack 的作用
    • seq:我这次发的包的序号
    • ack:我收到了你序号为 x 的包,下次请从 x+1 开始发
    • 这两个序号是 TCP 保证数据不丢、不乱序的核心。
  3. **TIME_WAIT 为什么要等?**因为第四次挥手的 ACK 如果丢了,B 收不到,就会一直重发 FIN 请求。A 等一会儿,是为了确保 B 能收到 ACK,避免 B 一直卡在断开状态。
相关推荐
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
AI职业加油站3 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
wuyk5553 天前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网
此冬歌咏3 天前
K8s 节点故障实战:优雅驱逐 31 秒,硬故障 331 秒,以及那个永远 Pending 的 Pod
运维·k8s
-梅3 天前
linux(8) 软硬链接
linux·运维·服务器
Wang's Blog3 天前
Java 项目实战: 外卖平台-文件下载与ServletOutputStream回写浏览器
服务器·项目开发
张洛闻Eren3 天前
k8s云原生【第十课】:水平 Pod 自动扩缩容
运维·数据库·云原生·kubernetes·github
琥珀色糖3 天前
SimlpeHttp
linux·服务器
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
第十人i3 天前
Linux 日志管理系统:journald 配置与优化
linux·服务器