【Linux网络】Linux 网络编程:传输层TCP(二)

🎬 个人主页艾莉丝努力练剑
专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:


文章目录

  • 前言
  • [1 ~> TCP 可靠性基础机制](#1 ~> TCP 可靠性基础机制)
    • [1.1 确认应答机制核心规则](#1.1 确认应答机制核心规则)
    • [1.2 无应答的判定与超时重传](#1.2 无应答的判定与超时重传)
    • [1.3 TCP 报文交互本质](#1.3 TCP 报文交互本质)
    • [1.4 TCP 可靠性的真正定义](#1.4 TCP 可靠性的真正定义)
  • [2 ~> TCP 报文两种发送工作模式](#2 ~> TCP 报文两种发送工作模式)
    • [2.1 串行停止等待模式](#2.1 串行停止等待模式)
    • [2.2 并行连续发送主流模式](#2.2 并行连续发送主流模式)
    • [2.3 两种模式适用场景](#2.3 两种模式适用场景)
  • [3 ~> TCP 序号与确认序号机制](#3 ~> TCP 序号与确认序号机制)
    • [3.1 引入序号与确认序号的原因](#3.1 引入序号与确认序号的原因)
    • [3.2 序号与接收缓冲区逻辑关系](#3.2 序号与接收缓冲区逻辑关系)
    • [3.3 TCP 数据段发送规则](#3.3 TCP 数据段发送规则)
    • [3.4 确认序号应答规则](#3.4 确认序号应答规则)
    • [3.5 乱序丢包场景下确认序号逻辑](#3.5 乱序丢包场景下确认序号逻辑)
      • [3.5.1 前置基础定义](#3.5.1 前置基础定义)
      • [3.5.2 第一步:正常无丢包场景的序号流转](#3.5.2 第一步:正常无丢包场景的序号流转)
      • [3.5.3 第二步:报文 3 丢失、报文 4 乱序到达的场景](#3.5.3 第二步:报文 3 丢失、报文 4 乱序到达的场景)
      • [3.5.4 第三步:接收方为什么只能返回 ACK=201,不能返回 ACK=401?](#3.5.4 第三步:接收方为什么只能返回 ACK=201,不能返回 ACK=401?)
      • [3.5.5 第四步:后续收到 ACK=401,为什么中间应答丢了也不用重传?](#3.5.5 第四步:后续收到 ACK=401,为什么中间应答丢了也不用重传?)
      • [3.5.6 核心结论](#3.5.6 核心结论)
    • [3.6 序号起始与序号回绕问题](#3.6 序号起始与序号回绕问题)
    • [3.7 双序号存在的必要性(捎带应答)](#3.7 双序号存在的必要性(捎带应答))
    • [3.8 序号三大核心功能](#3.8 序号三大核心功能)
    • [3.9 序号机制思维导图](#3.9 序号机制思维导图)
  • [4 ~> TCP 流量控制(16 位窗口大小)](#4 ~> TCP 流量控制(16 位窗口大小))
    • [4.1 流量控制产生背景](#4.1 流量控制产生背景)
    • [4.2 接收方接收能力量化标准](#4.2 接收方接收能力量化标准)
    • [4.3 16 位窗口大小字段作用](#4.3 16 位窗口大小字段作用)
    • [4.4 流量控制核心逻辑](#4.4 流量控制核心逻辑)
  • [5 ~> TCP 报头标志位体系](#5 ~> TCP 报头标志位体系)
    • [5.1 标志位本质与内核结构体定义](#5.1 标志位本质与内核结构体定义)
    • [5.2 六大核心标志位总述](#5.2 六大核心标志位总述)
    • [5.3 ACK 标志位](#5.3 ACK 标志位)
      • [5.3.1 ACK是什么?](#5.3.1 ACK是什么?)
      • [5.3.2 ACK标志位相关思维导图](#5.3.2 ACK标志位相关思维导图)
    • [5.4 SYN 标志位与三次握手](#5.4 SYN 标志位与三次握手)
      • [5.4.1 三次握手流程](#5.4.1 三次握手流程)
      • [5.4.2 连接的本质与内核管理](#5.4.2 连接的本质与内核管理)
      • [5.4.3 为什么必须三次握手](#5.4.3 为什么必须三次握手)
      • [5.4.4 三次握手与 socket 函数关系](#5.4.4 三次握手与 socket 函数关系)
      • [5.4.5 SYN标志位相关思维导图](#5.4.5 SYN标志位相关思维导图)
    • [5.5 FIN 标志位与四次挥手](#5.5 FIN 标志位与四次挥手)
      • [5.5.1 四次挥手完整状态流程](#5.5.1 四次挥手完整状态流程)
      • [5.5.2 为什么断开需要四次挥手](#5.5.2 为什么断开需要四次挥手)
      • [5.5.3 三次握手与四次挥手思想共性](#5.5.3 三次握手与四次挥手思想共性)
      • [5.5.4 FIN标志位相关思维导图](#5.5.4 FIN标志位相关思维导图)
    • [5.6 其余标志位简要说明](#5.6 其余标志位简要说明)
  • [6 ~> 连接关闭进阶:close 与 shutdown](#6 ~> 连接关闭进阶:close 与 shutdown)
    • [6.1 close 关闭连接特性](#6.1 close 关闭连接特性)
    • [6.2 shutdown 函数作用与参数](#6.2 shutdown 函数作用与参数)
    • [6.3 半关闭连接应用场景](#6.3 半关闭连接应用场景)
  • [7 ~> 核心知识点总结复盘](#7 ~> 核心知识点总结复盘)
  • 结尾


前言

前置导入语

在计算机网络体系结构中,传输层是承接应用层与网络层的核心枢纽,而 TCP 协议凭借面向连接、可靠传输、全双工通信、流量控制 等核心特性,成为互联网数据传输的基石。UDP 实现了无连接的快速传输,但无法保障数据可靠性,而 TCP 通过一整套完备的机制解决了网络传输中丢包、乱序、重复、收发速率不匹配等核心问题。

本文基于 TCP 协议深层原理,系统梳理 TCP 确认应答与超时重传机制、两种报文发送工作模式、32 位序号与确认序号核心原理、捎带应答机制、序号三大核心功能、16 位窗口大小流量控制机制、TCP 六大标志位核心作用,重点拆解ACK、SYN、FIN三大核心标志位,深度剖析 SYN 触发的三次握手建立连接原理、FIN 触发的四次挥手断开连接原理,同时结合内核缓冲区、连接本质、socket 编程接口、shutdown 与 close 区别等知识点,完整串联 TCP 下所有核心考点与底层逻辑,既适合零基础系统学习,也适合面试复盘、知识点回溯,构建完整的 TCP 传输层知识体系。

思维导图

bash 复制代码
传输层协议TCP(下)
├─ 1 TCP可靠性基础机制
│  ├─ 1.1 确认应答机制核心规则
│  ├─ 1.2 无应答的判定与超时重传
│  ├─ 1.3 TCP报文交互本质
│  └─ 1.4 TCP可靠性的真正定义
├─ 2 TCP报文两种发送工作模式
│  ├─ 2.1 串行停止等待模式
│  ├─ 2.2 并行连续发送主流模式
│  └─ 2.3 两种模式适用场景
├─ 3 TCP序号与确认序号机制
│  ├─ 3.1 引入序号与确认序号的原因
│  ├─ 3.2 序号与接收缓冲区逻辑关系
│  ├─ 3.3 TCP数据段发送规则
│  ├─ 3.4 确认序号应答规则
│  ├─ 3.5 乱序丢包场景下确认序号逻辑
│  ├─ 3.6 序号起始与序号回绕问题
│  ├─ 3.7 双序号存在的必要性(捎带应答)
│  └─ 3.8 序号三大核心功能
├─ 4 TCP流量控制(16位窗口大小)
│  ├─ 4.1 流量控制产生背景
│  ├─ 4.2 接收方接收能力量化标准
│  ├─ 4.3 16位窗口大小字段作用
│  └─ 4.4 流量控制核心逻辑
├─ 5 TCP报头标志位体系
│  ├─ 5.1 标志位本质与内核结构体定义
│  ├─ 5.2 六大核心标志位总述
│  ├─ 5.3 ACK标志位详解
│  ├─ 5.4 SYN标志位与三次握手
│  │  ├─ 5.4.1 三次握手流程
│  │  ├─ 5.4.2 连接的本质与内核管理
│  │  ├─ 5.4.3 为什么必须三次握手
│  │  └─ 5.4.4 三次握手与socket函数关系
│  ├─ 5.5 FIN标志位与四次挥手
│  │  ├─ 5.5.1 四次挥手完整状态流程
│  │  ├─ 5.5.2 为什么断开需要四次挥手
│  │  └─ 5.5.3 三次握手与四次挥手思想共性
│  └─ 5.6 其余标志位简要说明(URG/PSH/RST)
├─ 6 连接关闭进阶:close与shutdown
│  ├─ 6.1 close关闭连接特性
│  ├─ 6.2 shutdown函数作用与参数
│  └─ 6.3 半关闭连接应用场景
└─ 7 TCP(下)核心知识点总结复盘

本文大纲


1 ~> TCP 可靠性基础机制

1.1 确认应答机制核心规则

TCP是全双工 可靠传输协议,确认应答是可靠性的基础保障。应答由对方操作系统内核中的 TCP 协议栈自动回复,无需应用层参与。 通信核心规则:A 向 B 发送有效 TCP 数据,B 收到后自动返回应答;应答本身不需要再进行二次应答,否则会形成无限循环,违背传输效率设计。 全双工特性决定通信双方都要遵循确认应答规则,双向都能依靠该机制保障数据传输可靠性。

1.2 无应答的判定与超时重传

发送方收到应答:可 100% 确认接收方已经完整收到数据,传输可靠生效。 发送方未收到应答:无法区分原始数据丢失 还是应答报文丢失 ,TCP 统一规定:只要收不到应答,直接判定为丢包 。 为了界定 "是否没收到应答",TCP 引入超时时间 deadline 机制:设置固定超时阈值,若超时仍未收到对应应答,自动触发报文超时重传

1.3 TCP 报文交互本质

TCP 通信全程交互的单元是TCP 报文

  1. 发送方传输的有效数据,必须封装为完整 TCP 报文;
  2. 接收方返回的应答报文,即便不携带任何应用层有效数据,也必须保留TCP 报头,不能空报文传输。

1.4 TCP 可靠性的真正定义

TCP 可靠性并非强制保证数据一定发送成功,而是无论数据最终发送成功还是失败,发送方必须 100% 知晓最终结果。 例如网线断开、网络中断等场景,数据无法送达,TCP 可以精准感知传输失败状态,这才是可靠性的核心本质。


2 ~> TCP 报文两种发送工作模式

2.1 串行停止等待模式

基础工作逻辑:发送方每发送一个 TCP 数据包,必须等待收到对应应答后,才能发送下一个数据包 。 整个数据发送过程呈串行阻塞式 ,优点是逻辑简单、易于实现,缺点是时间无法重叠,整体传输效率偏低

2.2 并行连续发送主流模式

TCP 主流工作模式:发送方无需等待前序报文应答,可一次性连续发送批量 TCP 报文,仅保证每一个发出的报文最终都能收到对应应答。 报文收发时间可以重叠,从串行变为并行传输,极大提升网络吞吐和传输效率,是实际网络通信中默认采用的模式。

2.3 两种模式适用场景

  • 少量数据传输:默认采用串行停止等待模式,开销小、逻辑简单;
  • 大批量数据传输(文件、视频、网页资源等):固定采用并行连续发送模式,优先保障传输效率。

3 ~> TCP 序号与确认序号机制

3.1 引入序号与确认序号的原因

并行连续发送模式下,发送方一次性发出多个报文,若出现部分报文丢包,接收方无法区分具体哪个报文丢失,发送方也无法精准定位需要重传的报文。 为解决报文乱序、丢包定位、重复数据识别 问题,TCP 报头引入32 位序号、32 位确认序号一对核心字段。

3.2 序号与接收缓冲区逻辑关系

操作系统内核存在发送缓冲区、接收缓冲区 ,物理层面可理解为一个发送队列,内部以 sk_buff 结构存储数据,逻辑上可等效为数组。 缓冲区中的每一字节数据,天然拥有数组下标,TCP 序号在逻辑上直接对应缓冲区数据的字节下标

3.3 TCP 数据段发送规则

TCP 不会单个字节逐字节发送数据,而是批量分批发送 ,每一批数据称为TCP 数据段 。 示例:一次发送 1000 字节数据,起始下标为 1,结束下标为 1000,该报文序号标记为 1001;下一批数据从 1001 字节开始发送。 报文序号不连续的根本原因:每个 TCP 数据段都有固定数据长度,序号取当前数据段最后一个字节的下一位下标。

3.4 确认序号应答规则

基础算法:确认应答序号 = 接收报文序号 + 1 。 语义规则:返回的确认序号 N,代表序号 N 之前的所有字节数据,接收方已全部完整收到,发送方后续只需从序号 N 开始继续传输。 例:收到序号 1 的报文,应答确认序号为 101,告知发送方 101 之前数据全部接收完毕。

3.5 乱序丢包场景下确认序号逻辑

  • 多报文并行发送场景

假设报文1(起始序号1,长度100字节,携带字节1 ~ 100)、报文2(起始序号101,长度100字节,携带字节101 ~ 200)、报文3(起始序号201,长度100字节,携带字节201 ~ 300)、报文4(起始序号301,长度100字节,携带字节301 ~ 400)依次发送。

若起始序号为201的报文3丢失,而起始序号为301的报文4正常到达。

接收方只能确认序号201之前的数据(即报文1、报文2)已完整接收,因此对报文4的应答确认序号只能是201,而非401。

即便后续收到了确认序号为401的应答,只要确认序号标识前置数据已接收,即便中间201、301的应答报文丢失,也无需重复重传已接收的数据。

下面艾莉丝会详细阐释一下。

3.5.1 前置基础定义

TCP 是面向字节流的协议,所有数据都被编号为连续的字节序号,序号对应内核接收缓冲区的字节下标。

  • 报文起始序号:该报文携带的第一个字节的下标
  • 报文结束序号:该报文携带的最后一个字节的下标 = 起始序号 + 报文长度 - 1
  • 确认序号 ACK:接收方返回的「期望收到的下一个字节的下标」,语义为:我已经完整收到了 ACK 之前的所有字节(这是 TCP 累积确认的核心规则)

3.5.2 第一步:正常无丢包场景的序号流转

假设我们连续发送 4 个报文,每个报文长度都是 100 字节:

报文编号 起始序号 携带字节范围 结束序号 下一个报文的起始序号
报文 1 1 1~100 100 101
报文 2 101 101~200 200 201
报文 3 201 201~300 300 301
报文 4 301 301~400 400 401

正常情况下,接收方每收到一个报文,就返回对应的确认序号:

  • 收到报文 1 → 返回 ACK=101(表示 1~100 已收,下次请发 101)
  • 收到报文 2 → 返回 ACK=201(表示 1~200 已收,下次请发 201)
  • 收到报文 3 → 返回 ACK=301(表示 1~300 已收,下次请发 301)
  • 收到报文 4 → 返回 ACK=401(表示 1~400 已收,下次请发 401)

3.5.3 第二步:报文 3 丢失、报文 4 乱序到达的场景

发送方按顺序发送报文 1→报文 2→报文 3→报文 4,但网络传输中: 报文 1、报文 2 正常到达接收方

报文 3(201~300 字节)在网络中丢失 报文 4(301~400 字节)先于报文 3 到达接收方

此时接收方的缓冲区状态:

  • 已连续收到:1~200 字节(报文 1 + 报文 2)
  • 零散收到:301~400 字节(报文 4)
  • 缺失:201~300 字节(报文 3)

3.5.4 第三步:接收方为什么只能返回 ACK=201,不能返回 ACK=401?

这是 TCP累积确认的硬性规则:

确认序号只能标记「连续收到的最大字节的下一位」,不能跳过缺失的字节。

因为如果接收方返回 ACK=401,就相当于告诉发送方:"我已经收到了 1~400 的所有字节",但实际上 201~300 字节是缺失的,这会导致发送方误以为报文 3 已经送达,永远不会重传,最终数据丢失。

所以接收方只能基于连续收到的最大字节 200,返回确认序号 = 200+1=201,明确告诉发送方:"我只收到了 1~200 字节,接下来请从 201 字节开始发"。

3.5.5 第四步:后续收到 ACK=401,为什么中间应答丢了也不用重传?

发送方超时后,会重传报文 3(201~300 字节)。 接收方收到重传的报文 3 后,缓冲区就补齐了 1~400 的所有连续字节,此时会返回最终确认 ACK=401

这个 ACK=401 是累积确认 ,它的语义是:1~400 的所有字节,我已经全部收到了

  • 不管中间的 ACK=201、ACK=301 有没有丢失
  • 只要发送方最终收到了 ACK=401,就证明 1~400 字节全部送达
  • 因此不需要再重传任何报文,直接继续发送 401 及以后的字节即可

3.5.6 核心结论

  1. TCP 序号是字节级别的编号,不是报文级别的编号,序号不连续是因为每个报文携带多个字节
  2. 确认序号永远等于「已连续接收的最后一个字节序号 + 1」
  3. 乱序到达的报文会被接收方暂存,但不会更新确认序号,直到缺失的字节被补齐
  4. 累积确认机制允许中间应答丢失,只要最终收到最高序号的确认,就代表所有前置数据都已送达

3.6 序号起始与序号回绕问题

  1. TCP 报文序号不需要固定从 0 开始,单次收发周期内序号呈线性递增即可;
  2. 通信双方无需感知首个具体序号,只需要逻辑上默认从相对起始位置开始;
  3. 32 位序号需要传输 4GB 数据才会出现序号回绕,日常网络通信中几乎不会触发该问题,无需额外处理。

3.7 双序号存在的必要性(捎带应答)

疑问:为何需要序号和确认序号两个字段,只用一个是否足够? 核心原因:TCP 是全双工通信 ,且存在捎带应答机制。

  1. 全双工下通信双方都会互相发送数据、互相应答;
  2. 捎带应答:接收方无需单独发送应答报文,可将应答信息和自身业务数据合并在同一个 TCP 报文中发送,既充当数据报文、又充当应答报文;
  3. 合并后的报文既要携带自身发送数据的序号 ,又要携带对对方数据的确认序号,因此两个字段缺一不可。

3.8 序号三大核心功能

  1. 可靠性核心保障:配合确认应答、超时重传,精准定位丢包报文,实现可靠重传;
  2. 报文去重:超时重传会产生重复报文,接收方通过序号识别重复数据,直接丢弃冗余报文,避免上层应用收到重复数据;
  3. 保证按序到达:网络传输中存在 "早出发的报文不一定先到达" 的乱序问题,接收方依靠序号对乱序报文重新排序,保证数据按发送顺序交付给应用层,避免语义错乱。

3.9 序号机制思维导图


4 ~> TCP 流量控制(16 位窗口大小)

4.1 流量控制产生背景

若发送方发送数据速率过快,接收方内核接收缓冲区会被快速填满,后续到达的数据只能被直接丢弃。 丢弃的数据会触发 TCP 超时重传,反复重传会浪费网络资源、主机 CPU 与内存资源,传输效率极低,因此 TCP 必须引入流量控制机制。

4.2 接收方接收能力量化标准

接收方的接收能力,由内核接收缓冲区的剩余空闲空间大小唯一决定,剩余空间越大,接收能力越强;剩余空间越小,越无法处理新数据。

4.3 16 位窗口大小字段作用

TCP 报头中 16 位窗口大小字段,用于标识本机接收缓冲区剩余空闲空间。 通信双方在交互 TCP 报文时,应答报头中会携带自身窗口大小,双方可实时获取对方的接收能力。

4.4 流量控制核心逻辑

流量控制不是单纯限制发送方放慢速率,而是动态自适应调节

  1. 接收方缓冲区剩余空间小:告知发送方降低发送速率,避免数据溢出丢弃;
  2. 接收方缓冲区空闲充足:允许发送方加快发送速率,充分利用网络带宽;
  3. 双方通过 TCP 报头 16 位窗口大小实时同步接收状态,全程动态完成流量控制,平衡收发速率,避免资源浪费。

5 ~> TCP 报头标志位体系

5.1 标志位本质与内核结构体定义

TCP 报头包含 8 个标志位,实际重点使用 6 个,每个标志位占用1 个比特位 ,本质是用于区分 TCP 报文类型的字段。 内核中通过结构体位段定义标志位,源码结构如下:

c 复制代码
struct tcphdr{
    be16 source;
    be16 dest;
    be32 seq;
    __be32 ack_seq;
    #if defined(_LITTLE_ENDIAN_BITFIELD)
    u16 res1:4,
    doff:4,
    fin:1,
    syn:1,
    rst:1,
    psh:1,
    ack:1,
    urg:1,
    ece:1,
    cwr:1;
    #elif defined(BIG_ENDIAN BITFIELD)
    u16 doff:4,
    res1:4,
    cwr:1,
    ece:1,
    urg:1,
    ack:1,
    psh:1,
    rst:1,
    syn:1,
    fin:1;
    #else
    #error "Adjust your<asm/byteorder.h>defines"
    #endif
    be16window;
    sum16 check;
    _be16 urg_ptr;
};

不同报文(建连、断连、应答、紧急数据)通过置对应标志位为 1 来区分类型。

5.2 六大核心标志位总述

  1. URG:紧急指针是否有效,标识携带紧急数据;
  2. ACK:确认序号是否有效,标识当前报文为应答报文;
  3. PSH:提示接收端应用程序立即从 TCP 缓冲区读取数据,无需缓存积压;
  4. RST:复位标志,要求对方重新建立连接,丢弃当前异常连接;
  5. SYN:同步标志,用于请求建立 TCP 连接,同步报文段;
  6. FIN:结束标志,通知对方本端数据发送完毕,请求关闭连接,结束报文段。

5.3 ACK 标志位

5.3.1 ACK是什么?

ACK 全称 acknowledgment,核心作用:标记确认序号是否生效 ,置 1 代表当前报文是应答报文。 TCP 全双工通信中捎带应答机制普遍存在,绝大多数通信报文ACK 位都会置 1。 HTTP 协议通信双方地位不对等,而 TCP 通信双方地位完全对等,依靠 ACK 标志位完成双向应答。

5.3.2 ACK标志位相关思维导图

5.4 SYN 标志位与三次握手

5.4.1 三次握手流程

TCP 是面向连接协议,必须先建立连接再传输数据,连接建立依靠 SYN 标志位完成三次握手:

  1. 第一次握手:客户端向服务端发送SYN 报文(无应用数据,仅 TCP 报头),请求建立连接;
  2. 第二次握手:服务端收到 SYN 后,返回SYN+ACK 合并报文,既确认客户端建连意愿,也表达自身建连意愿;
  3. 第三次握手:客户端收到 SYN+ACK 后,返回ACK 应答报文,确认服务端意愿,双方连接进入 ESTABLISHED 已建立状态。

注意:通信过程中不会单独传输 SYN、ACK 比特位,只是 TCP 报头中对应标志位置 1,底层仍是标准 TCP 报文传输。

5.4.2 连接的本质与内核管理

  1. 服务器可同时维护海量客户端连接,操作系统遵循先描述,再组织原则管理连接;
  2. TCP 连接本质是操作系统内核中的一种专用数据结构,占用内存与时间资源,这也是 TCP 比 UDP 创建开销更大的原因;
  3. 应用层通过文件描述符 fd关联内核连接结构,使用 read/write/close 等系统调用控制连接。

5.4.3 为什么必须三次握手

两大核心核心理由:

  1. 验证全双工通信通畅 TCP 是全双工协议,通信前必须验证双方收发能力都正常:
  • 一次握手:无法验证任何收发能力;
  • 二次握手:仅能验证客户端收发正常、服务端可接收数据,无法验证服务端发送、客户端接收的能力;
  • 三次握手:以最小次数完整验证A 能发能收、B 能发能收,确保双向网络通路正常。
  1. 最小成本验证双方通信意愿 本质是互相确认是否愿意建立通信:原本需要四次交互(客户端 SYN、服务端 ACK、服务端 SYN、客户端 ACK),依靠捎带应答将服务端 SYN 和 ACK 合并为一个报文,四次简化为三次,在不丢失语义的前提下降低报文交互成本。 无需四次、五次握手,三次已满足所有校验需求,多余握手只会浪费网络与系统资源。

5.4.4 三次握手与 socket 函数关系

  1. 客户端调用connect()函数,自动发起第一次握手 SYN 请求,阻塞等待服务端应答;
  2. 服务端listen()将套接字设为监听状态,等待客户端连接;
  3. 服务端accept()不参与三次握手,仅在三次握手完成后,阻塞等待并返回新的连接文件描述符,用于和客户端专属通信。

5.4.5 SYN标志位相关思维导图

5.5 FIN 标志位与四次挥手

5.5.1 四次挥手完整状态流程

数据传输完成后,依靠 FIN 标志位断开 TCP 连接,标准为四次挥手,双方各自关闭读写通道:

  1. 第一次挥手:主动关闭方调用 close,发送 FIN 报文,告知对方本端不再发送数据;
  2. 第二次挥手:被动关闭端返回 ACK 应答,确认收到关闭请求,此时被动端仍可继续发送剩余数据;
  3. 第三次挥手:被动端数据全部发送完毕后,发送 FIN 报文,告知主动端自身也准备关闭;
  4. 第四次挥手:主动端返回 ACK 应答,确认关闭,经过 TIME_WAIT 状态后,双方连接彻底释放变为 CLOSED 状态。

状态流转:FIN_WAIT1、FIN_WAIT2、CLOSE_WAIT、LAST_ACK、TIME_WAIT、CLOSED。

5.5.2 为什么断开需要四次挥手

  1. 断开连接核心目的:以最小次数验证双方断开意愿,达成关闭共识;
  2. 全双工通信两端可独立完成数据发送,一方发完数据发送 FIN,另一方可能还有业务数据未传输完成,无法将 FIN 和 ACK 合并,不能像三次握手一样简化为三次;
  3. 只有等被动端所有数据发送完毕后,才能单独发送 FIN,因此必须固定四次交互;
  4. 极端场景下若双方同时无剩余数据,可能出现三次挥手,但属于小概率特例,标准断开流程为四次挥手。

5.5.3 三次握手与四次挥手思想共性

  1. 底层逻辑一致:都是通过标志位校验双方意愿,以最小交互次数完成目标;
  2. 三次握手侧重校验全双工通路 + 建连意愿,为后续通信做准备;
  3. 四次挥手侧重校验双方断连意愿,尊重双方各自数据发送完成的时间差。

5.5.4 FIN标志位相关思维导图

5.6 其余标志位简要说明

  • URG:紧急指针生效,优先传输紧急数据,无需等待缓冲区排队;
  • PSH:推送标志,触发应用层立即读取缓冲区数据,不做缓存滞留;
  • RST:复位标志,连接异常时强制断开、重置连接,丢弃无效连接状态。

6 ~> 连接关闭进阶:close 与 shutdown

6.1 close 关闭连接特性

close(fd)同时关闭读写两端的 TCP 通道,直接释放文件描述符与内核连接结构,一旦关闭,无法再收发任何数据。

6.2 shutdown 函数作用与参数

函数原型:

c 复制代码
#include <sys/socket.h>
int shutdown(int sockfd,int how);

功能:支持半关闭 TCP 全双工连接,可单独关闭读端、写端,或同时关闭,不直接释放文件描述符。 错误码:EBADF、EINVAL、ENOTCONN、ENOTSOCK 等,用于校验套接字合法性与连接状态。

6.3 半关闭连接应用场景

实际开发中若只需停止发送数据,但仍需要接收对方后续数据,不能使用 close,必须用 shutdown 仅关闭写通道,保留读通道,实现半双工通信场景下的灵活断连。 操作系统内核封装了所有 TCP 通信细节,上层应用无需感知丢包、重传、乱序排序等底层逻辑,这也是将传输层置于内核内部的核心设计初衷。


7 ~> 核心知识点总结复盘

  1. TCP 可靠性核心:依靠确认应答 + 超时重传实现,应答由对方 TCP 内核自动回复;可靠性是知晓传输结果,而非强制发送成功,无应答统一判定丢包并触发重传。
  2. 两种发送模式:串行停止等待效率低,适用于少量数据;并行连续发送是主流,通过序号解决乱序丢包问题,大幅提升传输效率。
  3. 序号与确认序号 :32 位序号对应缓冲区字节下标,按 TCP 数据段批量分配;确认序号遵循 "序号 + 1" 规则,标识前置数据全部接收;双序号因全双工 + 捎带应答 必不可少;序号具备去重、按序排序、可靠性保障三大核心功能。
  4. 流量控制:依靠 TCP 报头 16 位窗口大小,以接收缓冲区剩余空间量化接收能力,双方实时同步,动态调节收发速率,避免数据丢弃与资源浪费。
  5. 标志位核心:6 个核心标志位区分报文类型;ACK 标识应答报文,SYN 用于建连,FIN 用于断连;URG/PSH/RST 分别负责紧急数据、推送读取、连接复位。
  6. 三次握手核心 :面向连接必备流程,目的是验证全双工通路 + 最小成本确认双方建连意愿;通过捎带应答简化为三次,内核连接本质是数据结构,占用系统资源。
  7. 四次挥手核心:断开连接标准流程,因双方可独立发送数据,无法合并 FIN 与 ACK,必须四次交互确认断连意愿;与三次握手底层思想一致,都是校验双方意愿。
  8. 连接关闭:close 直接关闭读写全程、释放 fd;shutdown 支持半关闭,可单独关闭读 / 写端,适配只发不收、只收不发的业务场景;TCP 底层通信细节由内核屏蔽,上层应用无需感知。
  9. 捎带应答:TCP 全双工通信的核心优化机制,合并应答报文与数据报文,减少网络报文交互次数,既是双序号存在的原因,也是三次握手能简化的关键。

结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!" "技术之路难免有困惑,但同行的人会让前进更有方向。" |

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!

往期回顾

【Linux网络】Linux 网络编程:传输层TCP(一)

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა

相关推荐
A小辣椒3 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒7 小时前
TShark:基础知识
linux
AlfredZhao9 小时前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao1 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334661 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪1 天前
linux 拷贝文件或目录到指定的位置
linux
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质2 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式