一篇讲清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连接正式断开。

相关推荐
志栋智能8 分钟前
超自动化安全:构建智能安全运营的神经系统
大数据·运维·网络·人工智能·安全·自动化
华普微HOPERF20 分钟前
LoRa模块,如何通过卫星通信补齐地面网络的覆盖盲区?
网络·嵌入式硬件·模块·卫星通信
我先去打把游戏先21 分钟前
Ubuntu虚拟机(服务器版本)Git卸载完全教程——彻底移除与清理配置
服务器·git·单片机·嵌入式硬件·物联网·ubuntu·51单片机
着迷不白21 分钟前
四、Linux 文件权限+sudo权限委派+IO重定向+vim高级
linux·运维·服务器
WhoAmI23 分钟前
Linux 服务器挂载 LVM 逻辑卷全流程记录与问题排查
linux·服务器
quan_泉1 小时前
DIDCTF 取证初学者
java·服务器·前端
RisunJan1 小时前
Linux命令-nohup(使进程忽略挂起(HUP)信号并在后台继续运行)
linux·运维·服务器
爱喝水的鱼丶1 小时前
SAP-ABAP:SAP 简单报表输出开发系列(共6篇)第三篇:SAP ALV 报表样式定制:字段布局与交互功能配置
服务器·开发语言·学习·交互·sap·abap
键盘上的猫头鹰1 小时前
【Linux 基础教程(一)】概述、安装与网络配置:VMware + CentOS + NAT + XShell 远程连接
linux·网络·centos