深入理解 TCP 三次握手与四次挥手

目录

[一、TCP 三次握手](#一、TCP 三次握手)

[1.1 三次握手的目的](#1.1 三次握手的目的)

[1.2 三次握手流程](#1.2 三次握手流程)

[1.3 三次握手示意图](#1.3 三次握手示意图)

[二、TCP 四次挥手](#二、TCP 四次挥手)

[2.1 四次挥手的目的](#2.1 四次挥手的目的)

[2.2 四次挥手流程](#2.2 四次挥手流程)

[2.3 四次挥手示意图](#2.3 四次挥手示意图)

三、常见面试题解析

[3.1 为什么 TCP 建立连接是三次握手,而关闭连接是四次挥手?](#3.1 为什么 TCP 建立连接是三次握手,而关闭连接是四次挥手?)

[3.2 为什么 TCP 在四次挥手中要等待 2MSL?](#3.2 为什么 TCP 在四次挥手中要等待 2MSL?)

[3.3 为什么不能使用"两次握手"建立连接?](#3.3 为什么不能使用“两次握手”建立连接?)

四、总结


在计算机网络中,TCP(传输控制协议)是一种面向连接、可靠的、基于字节流的传输层通信协议。它的核心目标是确保数据的可靠传输 ,即数据在复杂的网络环境中既不会丢失也不会乱序。为了实现这一点,TCP 设计了独特的三次握手四次挥手机制,确保连接的稳定性和数据的完整性。

本文将详细讲解 TCP 的三次握手和四次挥手过程,并深入探讨背后的原理及面试常见问题。


一、TCP 三次握手

1.1 三次握手的目的

TCP 的三次握手旨在确认双方的接收和发送能力,并协商好初始序列号(ISN),为数据传输做好准备。

1.2 三次握手流程

以下是三次握手的详细步骤:

第一步:客户端 → 服务器

  • 客户端 发送一个带有 SYN(同步序列号)标志的 TCP 报文段。
  • 报文中包含客户端选择的初始序列号client_isn)。
  • 此时,客户端进入 SYN_SENT 状态,表示客户端已发送连接请求,等待服务器响应。

第二步:服务器 → 客户端

  • 服务器 收到客户端的 SYN 报文段后,向客户端发送一个 SYN + ACK 报文段。
  • 报文中包含:
    • 服务器选择的初始序列号server_isn)。
    • 对客户端 SYN 的确认号client_isn + 1)。
  • 此时,服务器进入 SYN_RCVD 状态,表示服务器已收到客户端的连接请求并同意建立连接。

第三步:客户端 → 服务器

  • 客户端 收到 SYN + ACK 报文后,向服务器发送一个 ACK 报文段。
  • 报文中包含:
    • 确认号server_isn + 1(确认已收到服务器的 SYN 报文)。
    • 序列号client_isn + 1
  • 此时,客户端进入 ESTABLISHED 状态,表示连接已建立。
  • 服务器收到 ACK 报文后,也进入 ESTABLISHED 状态。

至此,TCP 连接建立完成。

1.3 三次握手示意图

Lua 复制代码
客户端                               服务器
   SYN (client_isn)   -------->    SYN_RCVD
   SYN + ACK (server_isn) <-------- SYN_SENT
   ACK (server_isn + 1)  --------> ESTABLISHED

二、TCP 四次挥手

2.1 四次挥手的目的

TCP 的四次挥手用于安全地关闭连接,确保数据已传输完成,避免数据丢失。

2.2 四次挥手流程

以下是四次挥手的详细步骤:

第一次挥手:客户端 → 服务器

  • 客户端 发送一个带有 FIN(结束)标志的 TCP 报文段,表示客户端已经没有数据要发送,但仍可接收服务器的数据。
  • 报文中包含序列号client_seq)。
  • 此时,客户端进入 FIN_WAIT_1 状态。

第二次挥手:服务器 → 客户端

  • 服务器 收到 FIN 报文段后,向客户端发送一个 ACK 报文段确认收到 FIN
  • 报文中包含:
    • 确认号client_seq + 1
    • 序列号server_seq
  • 此时,服务器进入 CLOSE_WAIT 状态,客户端进入 FIN_WAIT_2 状态。

第三次挥手:服务器 → 客户端

  • 当服务器确认所有数据已发送完毕时,向客户端发送一个 FIN 报文段,表示服务器也已准备好断开连接。
  • 报文中包含序列号server_seq + 1
  • 此时,服务器进入 LAST_ACK 状态。

第四次挥手:客户端 → 服务器

  • 客户端 收到 FIN 报文段后,发送一个 ACK 报文段确认收到 FIN
  • 报文中包含:
    • 确认号server_seq + 2
    • 序列号client_seq + 1
  • 客户端进入 TIME_WAIT 状态并等待一段时间(2MSL)后关闭。
  • 服务器收到该 ACK 报文段后,进入 CLOSED 状态。

2.3 四次挥手示意图

Lua 复制代码
客户端                               服务器
   FIN (client_seq)  -------->     CLOSE_WAIT
   ACK (client_seq + 1) <--------  FIN_WAIT_2
   FIN (server_seq)   <--------    LAST_ACK
   ACK (server_seq + 2) -------->  CLOSED

三、常见面试题解析

3.1 为什么 TCP 建立连接是三次握手,而关闭连接是四次挥手?

原因:

  • 建立连接时,服务器可以将 SYNACK 合并在一个报文中,减少一次通信。
  • 关闭连接时,服务器可能还有未发送的数据,因此 FINACK 通常是分开发送的,从而多了一次挥手。

3.2 为什么 TCP 在四次挥手中要等待 2MSL?

**MSL(Maximum Segment Lifetime)**是一个数据包在网络中可能存活的最长时间。等待 2MSL 有以下两点原因:

  1. 确保服务器正确关闭连接:

    • 若客户端的 ACK 报文在传输中丢失,服务器会在超时后重发 FIN 报文。
    • 客户端在 2MSL 内能接收到这个 FIN 并重新发送 ACK,确保服务器安全关闭。
  2. 防止已失效的数据包干扰新连接:

    • 若客户端立刻关闭连接并重新发起新连接,之前网络中残留的旧数据包可能会被错误地当作新连接的数据,导致数据错乱。
    • 2MSL 的等待时间可确保之前的连接数据包完全消失。

3.3 为什么不能使用"两次握手"建立连接?

两次握手存在以下风险:

  • 若客户端的 SYN 包因网络延迟滞留在网络中,当客户端重新发送 SYN 并成功建立连接后,之前滞留的 SYN 包可能会再次到达服务器。
  • 服务器会误以为这是新的连接请求,从而建立错误的连接,导致资源浪费或数据错乱。

四、总结

  • 三次握手 是为了确认双方的收发能力 并协商初始序列号,确保数据传输的可靠性。
  • 四次挥手是为了确保数据传输完成后再安全断开连接,避免数据丢失。
  • 2MSL 等待机制保证了网络中的延迟数据包不会干扰新连接,是 TCP 保证可靠性的重要机制。

理解 TCP 的这些机制对网络编程、系统优化和面试应对至关重要。掌握这些知识,能够更好地理解 TCP 协议的精妙设计。

相关推荐
LCY1331 小时前
数据库与其所用数据结构
数据结构·数据库
日暮南城故里1 小时前
Java学习------初识JVM体系结构
java·jvm·学习
鱼樱前端1 小时前
Java Jdbc相关知识点汇总
java·后端
canonical_entropy2 小时前
NopReport示例-动态Sheet和动态列
java·后端·excel
kkk哥2 小时前
基于springboot的母婴商城系统(018)
java·spring boot·后端
程序漫游人2 小时前
Nginx参数调优脚本
运维·网络·nginx
王者鳜錸2 小时前
四、小白学JAVA-石头剪刀布游戏
java·开发语言·游戏
坚持学习永不言弃3 小时前
【IDEA】 配置安装 Leetcode 插件
java·leetcode·intellij-idea
Dust-Chasing3 小时前
数据结构之顺序表和栈
c语言·数据结构·算法