沉梦听雨的编程指南 沉梦听雨的编程指南
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 基础篇
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • RPC
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 多媒体框架
  • 虚拟机
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 随笔
  • 前端环境搭建
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • 脚手架搭建
  • 瑞吉外卖
  • 黑马点评
  • vue-blog
  • 沉梦接口开放平台
  • 用户中心
  • 聚合搜索平台
  • 仿12306项目
  • 壁纸小程序项目
  • RuoYi-Vue
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
Github (opens new window)

沉梦听雨

时间是最好的浸渍剂,而沉淀是最好的提纯器🚀
首页
  • 基础篇
  • 集合篇
  • 并发篇
  • JVM
  • 新特性
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 基础篇
  • MySql
  • Redis
  • 达梦数据库
  • Spring
  • SpringBoot
  • Mybatis
  • Shiro
  • 设计须知
  • UML画图
  • 权限校验
  • 设计模式
  • API网关
  • RPC
  • 消息队列
  • SpringCloud
  • 分布式事务
  • 云存储
  • 搜索引擎
  • 多媒体框架
  • 虚拟机
  • 开发工具篇
  • 工具库篇
  • 开发技巧篇
  • 工具类系列
  • 随笔
  • 前端环境搭建
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • 脚手架搭建
  • 瑞吉外卖
  • 黑马点评
  • vue-blog
  • 沉梦接口开放平台
  • 用户中心
  • 聚合搜索平台
  • 仿12306项目
  • 壁纸小程序项目
  • RuoYi-Vue
  • 博客搭建
  • 网站收藏箱
  • 断墨寻径摘录
  • 费曼学习法
Github (opens new window)
  • 网络

    • 网络核心知识总结
    • TCP 三次握手和四次挥手
      • 建立连接-三次握手
        • 什么是三次握手?
        • 为什么要三次握手?
        • TCP 为什么是三次握手,而不是两次或四次?
        • 第 2 次握手传回了 ACK,为什么还要传回 SYN?
      • 断开连接-四次挥手
        • 什么是四次挥手?
        • 为什么要四次挥手?
        • 为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手?
        • 如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样?
        • 为什么第四次挥手客户端需要等待 2*MSL(报文段最长寿命)时间后才进入 CLOSED 状态?
        • 什么是 MSL?
      • 学习参考
    • TCP 传输可靠性问题
    • 常见状态码总结
    • 响应内容的几种接收类型
    • Header请求头部详解
    • 《计算机网络》谢希仁
    • 日常网络小知识
  • 操作系统

  • 数据结构与算法

  • 计算机基础
  • 网络
沉梦听雨
2023-06-12
目录

TCP 三次握手和四次挥手

# TCP 三次握手和四次挥手

# 建立连接-三次握手

# 什么是三次握手?

简单来说:

  1. 客户端向服务器发送 SYN 报文,请求建立连接。
  2. 服务器收到 SYN 报文后,回复一个 SYN+ACK 的报文,表示同意建立连接。
  3. 客户端收到 SYN+ACK 报文后,再回复一个 ACK 报文,表示确认连接已经建立。

SYN -- Synchronize 连接信号;ACK -- Acknowledgment 确认信号;SEQ -- Sequence Number 是序列号,用于标识报文段中的数据字节的顺序

建立一个 TCP 连接需要“三次握手”,缺一不可:

  1. 一次握手:
    • 客户端发送带有 SYN(SEQ=x)标志的数据包 -> 服务端,
    • 然后客户端进入 SYN_SEND 状态,等待服务器的确认;
  2. 二次握手:
    • 服务端发送带有 SYN+ACK(SEQ=y,ACK=x+1) 标志的数据包 –> 客户端,
    • 然后服务端进入 SYN_RECV 状态
  3. 三次握手:
    • 客户端发送带有 ACK(ACK=y+1) 标志的数据包 –> 服务端,
    • 然后客户端和服务器端都进入 ESTABLISHED(established) 状态,完成 TCP 三次握手。

当建立了 3 次握手之后,客户端和服务端就可以传输数据了。

具体如下图所示:

TCP三次握手

# 为什么要三次握手?

三次握手的主要目的是:确保客户端和服务器之间建立了可靠的连接,同时避免因重复的连接请求造成网络资源的浪费。

  1. 第一次握手:
    • Client 什么都不能确认;
    • Server 确认了对方发送正常,自己接收正常
  2. 第二次握手:
    • Client 确认了:自己发送、接收正常,对方发送、接收正常;
    • Server 确认了:对方发送正常,自己接收正常
  3. 第三次握手:
    • Client 确认了:自己发送、接收正常,对方发送、接收正常;
    • Server 确认了:自己发送、接收正常,对方发送、接收正常

# TCP 为什么是三次握手,而不是两次或四次?

因为,三次握手是为了确保连接的可靠性和避免网络资源的浪费。而两次握手会存在上述的问题,四次握手则会增加不必要的开销,所以三次握手是一种较为合理的选择。

# 第 2 次握手传回了 ACK,为什么还要传回 SYN?

服务端传回发送端所发送的 ACK 是为了告诉客户端:“我接收到的信息确实就是你所发送的信号了”,这表明从客户端到服务端的通信是正常的。

回传 SYN 则是为了建立并确认从服务端到客户端的通信。

什么是 SYN ?

SYN 同步序列编号(Synchronize Sequence Numbers) 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement)消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。

# 断开连接-四次挥手

# 什么是四次挥手?

简单来说:

  1. 客户端向服务器发送 FIN 报文,请求关闭连接。
  2. 服务器收到 FIN 报文后,回复一个 ACK 报文,确认已经收到客户端的请求。
  3. 服务器再向客户端发送一个 FIN 报文,表示服务端也准备关闭连接。
  4. 客户端收到服务器的 FIN 报文后,回复一个 ACK 报文,确认已经收到服务端的请求,并关闭连接。

具体如下图所示:

TCP四次挥手

断开一个 TCP 连接则需要“四次挥手”,缺一不可:

  1. 第一次挥手:

    • 客户端发送一个 FIN(SEQ=x) 标志的数据包->服务端,用来关闭客户端到服务器的数据传送。

    • 然后,客户端进入 FIN-WAIT-1 状态。

  2. 第二次挥手:

    • 服务器收到这个 FIN(SEQ=X)标志的数据包,它发送一个 ACK(ACK=x+1)标志的数据包 -> 客户端。
    • 然后,此时服务端进入 CLOSE-WAIT 状态,客户端进入 FIN-WAIT-2 状态。
  3. 第三次挥手:

    • 服务端关闭与客户端的连接并发送一个 FIN(SEQ=y) 标志的数据包 -> 客户端,请求关闭连接,
    • 然后,服务端进入 LAST-ACK 状态。
  4. 第四次挥手:

    • 客户端发送 ACK (ACK=y+1) 标志的数据包 -> 服务端并且进入 TIME-WAIT 状态,
    • 服务端在收到 ACK (ACK=y+1) 标志的数据包后进入 CLOSE 状态。
    • 此时,如果客户端等待 2MSL 后依然没有收到回复,就证明服务端已正常关闭,随后,客户端也可以关闭连接了。

只要四次挥手没有结束,客户端和服务端就可以继续传输数据!

# 为什么要四次挥手?

TCP四次挥手的主要目的是:确保客户端和服务器之间的连接能够正常关闭,并且避免因为未处理完的数据包而造成数据的丢失和不完整。

即:为了确保连接的正常关闭和数据的完整性

# 为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手?

因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复 ACK,表示接收到了断开连接的请求。等到数据发完之后再发 FIN,断开服务器到客户端的数据传送。

ACK 的作用是: 确认收到对方发送的数据包,

而 FIN 的作用是: 请求关闭连接。

# 如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样?

客户端没有收到 ACK 确认,会重新发送 FIN 请求。

# 为什么第四次挥手客户端需要等待 2*MSL(报文段最长寿命)时间后才进入 CLOSED 状态?

因为第四次挥手时,客户端发送给服务器的 ACK 有可能会丢失。

如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN,

如果客户端在 2*MSL 的时间内收到了 FIN,就会重新发送 ACK 并再次等待 2MSL,防止 Server 没有收到 ACK 而不断重发 FIN。

假设客户端在发送 ACK 之后立即进入 CLOSED 状态(即关闭连接),同时 服务端没有接收到客户端的 ACK 确认,就会一直重发 FIN -- 请求关闭连接。

# 什么是 MSL?

MSL(Maximum Segment Lifetime): 一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个回复所需的最大时间。如果直到 2MSL,Client 都没有再次收到 FIN,那么 Client 推断 ACK 已经被成功接收,则结束 TCP 连接。

# 学习参考

  • TCP 三次握手和四次挥手(传输层) | JavaGuide(Java面试 + 学习指南) (opens new window)
上次更新: 2024/9/25 11:16:13
网络核心知识总结
TCP 传输可靠性问题

← 网络核心知识总结 TCP 传输可靠性问题→

Theme by Vdoing | Copyright © 2023-2025 沉梦听雨 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式