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

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

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

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

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

核心目标

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

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

角色分工

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

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

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

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

A 给 B 打电话:

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

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

B 给 A 回电话:

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

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

A 再回 B 一句:

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

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

B 回 A:

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

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

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

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

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

A 回 B:

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

  • 对应报文:ACK=1ack=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 一直卡在断开状态。
相关推荐
XiYang-DING3 小时前
【Java EE】IP协议
网络·tcp/ip·java-ee
YIN_尹3 小时前
【Linux 系统编程】手撕一个简易版的shell命令行解释器
android·linux·运维
小脑斧1234 小时前
从入门到精通:Linux 进程间通信 IPC 全解析|管道、共享内存、信号量、消息队列实战
linux·运维·服务器
難釋懷4 小时前
Nginx反向代理
运维·nginx
tom02184 小时前
2026年5月23日软考中级网络工程师考题答案整理
网络·网络工程师·软考·答案·试题·2026年
ABCDEEE74 小时前
3.RAG
java·linux·服务器
优化Henry4 小时前
LTE站点8通道RRU单通道驻波异常导致小区服务降级案例分析
运维·服务器·5g·信息与通信
为思念酝酿的痛4 小时前
Linux线程
linux·服务器·后端
樱桃花下的小猫4 小时前
幻兽帕鲁(Palworld)存档迁移与角色修复完全指南
服务器·幻兽帕鲁·新手友好·云鸢互联·零门槛一键开服·幻兽帕鲁服务器