ShuangChenYue ShuangChenYue
首页
  • Cpp之旅
  • Cpp专栏
  • Effective_CPP
  • muduo网络库
  • Unix环境高级编程
  • Cpp提高编程
  • 计算机网络
  • 操作系统
  • 数据结构
  • Linux
  • 算法
  • 基础篇
  • MySql
  • Redis
  • 电子嵌入式通信协议
  • 深入浅出SSD
  • 文件系统
  • 汇编语言
  • STM32
  • 随笔(持续更新)
  • Git知识总结
  • Git 创建删除远程分支
  • nvm使用小结
  • 虚拟机固定 IP 地址
  • Shell 脚本学习笔记
  • VScode 插件 CodeGeeX 使用教程
  • KylinV10 将项目上传至 Github教程
  • KylinV10 安装 MySQL 教程(可防踩雷)
  • kylinV10-SP1 安装 QT
  • 高并发内存池
  • USBGUARD 项目编译环境配置
  • Power_Destory 项目
  • U 盘清除工具编译教程
  • 个人博客代码推送教程
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • MFC编程随记
  • MFC实现ini配置文件的读取
  • MFC实现点击列表头排序
  • 贴图法美化Button按钮
  • 如何高效阅读嵌入式项目代码
  • NAND Flash
  • ARM 处理器
  • 嵌入式基础知识-存储器
  • 闪存存储和制造技术概述
  • 芯片IO驱动力
  • 主流先进封装技术介绍
  • 虎牙C++技术面经
  • 金山一面复习
  • 完美世界秋招 C++ 游戏开发面经(Cpp部分)
  • 博客搭建
  • 网站收藏箱
首页
  • Cpp之旅
  • Cpp专栏
  • Effective_CPP
  • muduo网络库
  • Unix环境高级编程
  • Cpp提高编程
  • 计算机网络
  • 操作系统
  • 数据结构
  • Linux
  • 算法
  • 基础篇
  • MySql
  • Redis
  • 电子嵌入式通信协议
  • 深入浅出SSD
  • 文件系统
  • 汇编语言
  • STM32
  • 随笔(持续更新)
  • Git知识总结
  • Git 创建删除远程分支
  • nvm使用小结
  • 虚拟机固定 IP 地址
  • Shell 脚本学习笔记
  • VScode 插件 CodeGeeX 使用教程
  • KylinV10 将项目上传至 Github教程
  • KylinV10 安装 MySQL 教程(可防踩雷)
  • kylinV10-SP1 安装 QT
  • 高并发内存池
  • USBGUARD 项目编译环境配置
  • Power_Destory 项目
  • U 盘清除工具编译教程
  • 个人博客代码推送教程
  • HTML与CSS
  • JS学习
  • Vue3入门
  • Vue3进阶
  • 黑马Vue3
  • MFC编程随记
  • MFC实现ini配置文件的读取
  • MFC实现点击列表头排序
  • 贴图法美化Button按钮
  • 如何高效阅读嵌入式项目代码
  • NAND Flash
  • ARM 处理器
  • 嵌入式基础知识-存储器
  • 闪存存储和制造技术概述
  • 芯片IO驱动力
  • 主流先进封装技术介绍
  • 虎牙C++技术面经
  • 金山一面复习
  • 完美世界秋招 C++ 游戏开发面经(Cpp部分)
  • 博客搭建
  • 网站收藏箱
  • 网络

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

  • 数据结构

  • 算法

  • Linux

  • 计算机基础
  • 网络
霜晨月
2023-06-12
目录

TCP 三次握手和四次挥手

# TCP 三次握手和四次挥手

# 建立连接-三次握手

# 什么是三次握手?

简单来说:

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

SYN -- Synchronize 连接信号;ACK -- Acknowledgment 确认信号

建立一个 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 次握手之后,客户端和服务端就可以传输数据了。

具体如下图所示:

image

# 为什么要三次握手?

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

  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 报文,确认已经收到服务器的请求,并关闭连接。

具体如下图所示:

image

断开一个 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 连接。

上次更新: 2024/6/3 14:54:44
网络核心知识总结
TCP 传输可靠性问题

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

Theme by Vdoing | Copyright © 2023-2024 霜晨月
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式