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

一、先搞懂背景: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 一直卡在断开状态。
相关推荐
skywalk81639 分钟前
通过下载Ubuntu ova文件在Virtual Box快速安装ubuntu
linux·运维·ubuntu·virtualbox
姚不倒13 分钟前
HAProxy 系列(四):多中间件统一 VIP 入口 — 架构模式与最佳实践
运维·中间件·架构·haproxy
happymade24 分钟前
7000 台网络设备批量纳管 & 自动拓扑生成实战——MSRM3 完整操作流程与关键要点复盘
运维·服务器·网络·zabbix·grafana·msrm3
啊阿狸不会拉杆34 分钟前
《计算机网络-自顶向下方法》4.1 网络层概述 读书笔记
网络·计算机网络·智能路由器·网络层
做萤石二次开发的哈哈38 分钟前
萤石蓝海 AIoT 一站式工作台:海康LCD会议平板接入,多端大屏运维应用一站生成
运维·物联网·电脑·萤石开放平台·会议室管理·蓝海aiot一站式工作台·otap物模型
Shadow(⊙o⊙)1 小时前
Linux网络——文件与网络的连接桥梁struct sock {
linux·运维·网络
李永奉1 小时前
中科蓝讯SDK开发-提示音音频文件格式转换和压缩教程
网络·单片机·嵌入式硬件·mcu·物联网
其实防守也摸鱼1 小时前
教育信息技术应用创新---基础软件信息赛(题库)
大数据·运维·人工智能·web安全·自动化
新时代牛马1 小时前
Linux 性能调优与追踪完整篇:ftrace、perf、eBPF从采样到落地验证
linux·运维·服务器
sunoo-2291 小时前
【网络编程 + 数据库】select 与 epoll 核心区别详解 + SQLite 入门到 C 接口全攻略
linux·网络·数据库·vscode·学习·sqlite