一篇讲清TCP的三次握手&四次挥手

目录

TCP连接

三次握手(建立连接)

第一次握手

第二次握手

第三次握手

常见问题

为什么是三次握手,而不是二次或四次。

四次挥手(断开连接)

第一次挥手

第二次挥手

第三次挥手

第四次挥手

TCP连接

TCP位于OSI七层网络模型中的第四层传输层,它的核心任务只有一个:在不可靠的IP网络层之上,构造一个可靠的面向连接的字节流的连接通道。

这里有三个关键词:

  1. 靠的:保证传输的信息报文不丢,不乱,不错。
  2. 面向连接的:传递信息报文之前要建立连接,保证连接通道可正常传输信息。这就是本章重点:三次握手&四次挥手
  3. 字节流的:TCP把数据看作一连串无结构的字节流。

要了解三次握手和四次挥手的过程,首先要了解TCP报文的组成。TCP报文由头部数据两部分组成,我们主要看头部,它包含了TCP工作的所有控制信息。

上图就是TCP报文段的头部,通常是20个字节,我们主要关注五个核心字段

  1. 源端口号&目的端口号(各占两字节):IP地址解决了信息发送到哪台电脑的问题,而端口号解决了数据发送到的电脑上哪个进程的问题。
  2. 序列号Seq(四字节):本报文段所发送的数据的第一个字节的序号,解决网络包乱序的问题。
  3. 确认号ack(四字节):表示期望收到对方下一个报文段的第一个数据字节的序列号。
  4. 标志位 :有几个重要的标志位
    • SYN:同步位。SYN=1 表示这是连接同步报文,用于初始化序列号;仅在三次握手的前 2 个报文中置 1;建立连接。简单点说就是表明这次通信适用于建立连接的。不是用于传输数据的。SYN=1,此次传输不能携带数据。
    • ACK:确认位。ACK=1 表示确认号 ack 字段有效;TCP 规范强制规定:连接建立完成后,所有传输的报文段必须将 ACK 置 1。
    • FIN:关闭连接
    • RST:重置异常链接
  5. 窗口大小:接收缓冲区还能容纳多少字节数据。这是实现流量控制的基础。

!!!注意,大写的ACK和小写的ack不是一个东西!!!大写的ACK是一个标识,只有1bit,ACK=1 表示确认号 ack 字段有效,而小写的ack是序列号,有32bit。

也可以简单理解成ACK=1时,ack才会启用,不然是无效的。

三次握手(建立连接)

第一次握手

客户端向服务端发起连接请求。同步自己的初始序列号。

状态变化:客户端从 CLOSED → SYN_SENT(同步已发送)

报文头部字段变化:

  • SYN = 1(表明这是一次连接同步报文
  • Seq = x(随机生成)
  • ACK = 0
  • ack = 0(ACK=0,ack无效,默认为0)

关键说明 :该报文仅用于同步序列号,不能携带应用数据;因 SYN=1,该报文固定消耗 1 个序列号,后续服务端的 ack 必须为 x+1。

第二次握手

服务端收到客户端的 SYN 请求后,同时完成两件事:① 确认客户端的同步请求;② 向客户端同步自己的初始序列号。

状态变化:服务端从 LISTENSYN_RCVD(同步已收到)

报文头部字段变化:

  • SYN = 1(表明这是一次连接同步报文
  • Seq = y(随机生成)
  • ACK = 1(开启确认功能,ack 字段生效)
  • ack = x + 1(上一次握手客户端传过来Seq = x + SYN消耗的一个字节。代表服务端已完整收到客户端 Seq = x 的报文,期望下一次收到客户端的 Seq 从 x+1开始)

关键说明 :这是三次握手中唯一同时将 SYN 和 ACK 置 1 的报文,不能携带应用数据 ;因 SYN=1,该报文固定消耗 1 个序列号,后续客户端的 ack 必须为 y+1

第三次握手

客户端收到服务端的 SYN+ACK 后,向服务端发送最终确认报文,完成连接建立。

状态变化:客户端从 SYN_SENTESTABLISHED(连接已建立);服务端收到该报文后,从 SYN_RCVDESTABLISHED(连接已建立),全双工连接正式建立。

报文头部字段变化:

  • SYN = 0(初始序列号同步完成,无需再置位)
  • Seq = x + 1(随机生成)
  • ACK = 1(开启确认功能,ack 字段生效)
  • ack = y + 1(上一次握手客户端传过来Seq = y + SYN消耗的一个字节。代表客户端已完整收到服务端 Seq=y的报文,期望下一次收到服务端的 Seq 从 y+1开始)

关键说明 :该报文可以携带应用数据:如果不携带数据,不消耗序列号;如果携带数据,消耗对应数据长度的序列号。

常见问题

为什么是三次握手,而不是二次或四次。

答:核心是为了避免失效的连接请求报文传到服务端,建立无效的连接,浪费系统资源。同时,只有三次握手客户端和服务端才能确认彼此都有接收和发送的能力。如果没有第三次握手,服务端无法确认客户端的接收能力。

  • 第一次客户端向服务端发送SYN报文,服务端接收报文。此时服务端确认客户端有发送能力。
  • 第二次服务端向客户端发送SYN报文,客户端接收报文。此时客户端确认服务端有接收和发送能力。
  • 第三次客户端向服务端发送报文,服务端接收报文。此时服务端确认客户端有接收能力。

四次挥手(断开连接)

客户端与服务端建立的TCP连接是**全双工通信协议,**也就是说要想断开一个TCP连接,就必须双方都确认关闭自己的发送通道,这就是 "四次挥手" 的根本原因。而断开连接的发起者,可以是客户端,也可以是服务端。(下面我们以客户端为发起者演示)

第一次挥手

客户端向服务端发送FIN报文,序号为**seq=u**(u 是客户端当前已发送数据的最后一个字节序号 + 1)

客户端状态 :从ESTABLISHED 变为FIN_WAIT_1

含义:"我客户端没有数据要发给你了,我要关闭我到你的发送通道"

第二次挥手

服务器 收到 FIN 后,立即发送一个ACK=1 的报文段,确认号为ack=u+1,序号为**seq=y**(y 是服务器当前已发送数据的最后一个字节序号 + 1)

服务器状态 :从ESTABLISHED 变为CLOSE_WAIT

客户端状态 :收到 ACK 后,从FIN_WAIT_1 变为FIN_WAIT_2

含义:"我服务器收到了你关闭发送通道的请求,我确认了"

第二次挥手结束后,客户端已经关闭发送数据报文的通道了。但是还可以发送控制报文(ACK、FIN、RST、SYN),来辅助服务端关闭连接通道。

第三次挥手

当服务器也没有数据要发送给客户端时,调用close()函数,发送一个FIN=1,ACK=1 的报文段,确认号仍然是**ack=u+1,序号为seq=w**(w 是服务器在 CLOSE_WAIT 状态下发送的最后一个字节序号 + 1)

服务器状态 :从CLOSE_WAIT 变为LAST_ACK

含义:"我服务器也没有数据要发给你了,我也要关闭我到你的发送通道"

第四次挥手

客户端操作 :收到 FIN 后,立即发送一个ACK=1 的报文段,确认号为ack=w+1,序号为seq=w+1

客户端状态 :从FIN_WAIT_2 变为TIME_WAIT

服务器状态 :收到 ACK 后,从LAST_ACK 变为CLOSED,连接完全关闭

客户端后续 :在TIME_WAIT 状态等待2MSL (最长报文段寿命)时间后,也变为CLOSED状态

含义:"我客户端收到了你关闭发送通道的请求,我确认了"

至此,TCP连接正式断开。

相关推荐
Mike117.1 小时前
GBase 8a 物化视图依赖和 DDL 风险排查记录
java·服务器·前端
tang777891 小时前
2026年国内代理IP服务商横向测评:企业级爬虫如何选型?
运维·服务器·网络·爬虫·python·代理
上海云盾-小余1 小时前
网站木马植入原理与彻底清除、长效防御方案
网络·网络协议·tcp/ip·系统安全
Be reborn1 小时前
用 Playwright 做自动化测试:如何验证网络请求并做断言
网络·python·自动化·pytest
www.021 小时前
Linux 终端守护神 Tmux :如何优雅地管理后台实验与恢复会话
linux·运维·服务器·人工智能·tmux
VOOHU-沃虎1 小时前
工业以太网接口的隐形门槛:网络变压器选型失当的故障分析与系统性验证
网络
广州灵眸科技有限公司2 小时前
瑞芯微(EASY EAI)RV1126B yolov11-track多目标跟踪部署教程
linux·开发语言·网络·人工智能·yolo·机器学习·目标跟踪
牵牛老人2 小时前
CAN通讯实战:Qt基于周立功 USBCAN 的 CAN 总线通信开发全攻略
网络·qt·系统架构
谷雨不太卷2 小时前
计算机网络:套接字
linux·服务器·计算机网络