TCP 三次握手四次挥手

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

目的:确认双方的接收和发送能力都正常。

  1. 第一次握手 (Client -> Server):

    • 动作: 客户端发送一个 SYN=1 的包,并带上一个随机序列号 Seq=x。

    • 状态转换: 客户端进入 SYN_SENT 状态。

    • 物理意义: 客户端问:"喂,你能听到我说话吗?"

  2. 第二次握手 (Server -> Client):

    • 动作: 服务端收到后,发送 SYN=1, ACK=1,确认号 Ack=x+1,并带上自己的随机序列号 Seq=y。

    • 状态转换: 服务端进入 SYN_RCVD 状态。

    • 物理意义: 服务端回答:"我听到了!那你也能听到我说话吗?"(这里把 ACK 确认应答和 SYN 询问合并在一个包里发了)。

  3. 第三次握手 (Client -> Server):

    • 动作: 客户端收到后,发送 ACK=1,确认号 Ack=y+1。

    • 状态转换: 客户端和收到该包的服务端都进入 ESTABLISHED(已连接)状态。

    • 物理意义: 客户端回答:"我也能听到!"。至此,双方都确认了彼此的收发能力正常,连接建立。

面试常问:为什么是三次,不是两次或四次?

  • 为什么不能是两次? 如果只有两次,服务端发完第二次握手包后就以为连接建立成功了。但如果这个包在网络中丢失,客户端根本没收到。此时服务端一直傻等,浪费资源;或者网络中延迟的旧请求突然到达服务端,服务端以为是新连接,导致状态错乱(防止已失效的连接请求报文段突然又传送到了服务端)。

  • 为什么不是四次? 第二步中,服务端把确认对方的 ACK 包和询问对方的 SYN 包合并成了一个,优化了效率,所以不需要四次。


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

目的:优雅地断开双向通道,确保所有数据都传输完毕。 挥手的核心在于 TCP 是全双工的(双向通道独立)。所以,一方关掉发送通道,不代表它不能接收数据了,这叫做"半关闭 (Half-Close)"状态。

  1. 第一次挥手 (Client -> Server):

    • 动作: 客户端数据发完了,主动发送 FIN=1 的包。

    • 状态转换: 客户端进入 FIN_WAIT_1 状态。

    • 物理意义: 客户端说:"我没数据要发了,准备关门了。"

  2. 第二次挥手 (Server -> Client):

    • 动作: 服务端收到 FIN,立刻回复 ACK=1。

    • 状态转换: 服务端进入 CLOSE_WAIT,客户端收到后进入 FIN_WAIT_2。

    • 物理意义: 服务端说:"好的,我知道你发完了。但我可能还有数据没发完,你等我一下。" (此时 Client 到 Server 的通道关闭,但 Server 到 Client 的通道还在,Server 可以继续发业务数据)。

  3. 第三次挥手 (Server -> Client):

    • 动作: 服务端的数据也发完了,发送 FIN=1 的包给客户端。

    • 状态转换: 服务端进入 LAST_ACK 状态。

    • 物理意义: 服务端说:"我的数据也发完了,我也准备关门了。"

  4. 第四次挥手 (Client -> Server):

    • 动作: 客户端收到 FIN,回复 ACK=1。

    • 状态转换: 客户端进入 TIME_WAIT 状态。服务端收到后直接进入 CLOSED 状态。客户端等 2MSL 时间后,也进入 CLOSED 状态。

    • 物理意义: 客户端说:"收到,你关吧。" 然后客户端在原地等一会儿,确认服务端真的关了,自己才彻底关机。

面试常问:为什么握手是三次,挥手却要四次? 握手时,服务端可以把 ACK(确认)和 SYN(申请连接)合并 在同一个包里发。但挥手时,服务端收到 FIN 只能先回一个 ACK 表示"我收到了"。此时服务端可能还要继续处理业务,把缓冲区里剩下的数据发完,不能马上发 FIN。所以 ACK 和 FIN 只能分两步发,导致总共需要四次。

相关推荐
叼烟扛炮2 小时前
Linux 学习笔记(五十九):epoll 的生死抉择——LT 与 ET 模式
linux·运维·服务器·网络·笔记·学习·php
Android系统攻城狮9 小时前
Linux FFmpeg深度解析之avcodec_align_dimensions调用流程与实战(二十九)
服务器·linux音视频·音视频进阶·ffmpeg音视频
叼烟扛炮10 小时前
Linux 学习笔记(五十六):IO 多路复用初探——select 的“三宗罪”
linux·服务器·数据库·笔记·学习·php
Ruiery10 小时前
Linux 6.6内核内存管理深度解析(十五):CMA 连续内存分配器
linux·运维·服务器
测试界的小码农11 小时前
【Linux 命令实战(01):认识 Linux 终端,从零掌握第一个命令】
linux·运维·服务器
zhikouai13 小时前
把外部助手接进聊天软件的架构分层与参数配置
服务器·网络·php
荣合技术服务13 小时前
HPC 超算集群故障维修实录:找荣合科算维护后,模拟仿真计算又能跑了
运维·服务器·超算服务器·荣合科算
叼烟扛炮16 小时前
Linux 学习笔记(五十八):IO 多路复用封神——epoll 底层原理揭秘
linux·运维·服务器·网络·笔记·学习·php
叼烟扛炮17 小时前
Linux 学习笔记(五十一):数据链路层与 ARP 协议——局域网寻址与黑客骗局
linux·网络·网络协议·php·tcpdump
星恒随风17 小时前
Linux网络编程:彻底理解IO多路复用select!从fd_set位图、读写就绪到手写TCP多客户端字典服务器
linux·服务器·网络