Linux TCP 协议深度解析:从状态机到拥塞控制

引言

TCP(传输控制协议)是互联网的基石协议之一。它提供了面向连接、可靠、基于字节流的传输服务。与UDP的简单封装不同,TCP通过复杂的机制保证了数据在网络中传输的可靠性。

本文将从TCP的核心特性出发,深入讲解连接状态机、三次握手与四次挥手、TIME_WAIT状态的意义,以及拥塞控制算法等高级主题。


第一部分:TCP 协议核心特性

一、协议特点

特性 说明
面向连接 通信前必须建立连接(三次握手),结束后断开连接(四次挥手)
可靠传输 通过确认应答、超时重传、去重、乱序重排保证可靠性
流式服务 数据以字节流形式传输,无固定边界
全双工通信 双方可同时发送和接收数据

二、可靠性实现机制

确认应答(ACK):接收方收到数据后发送确认信息,告知发送方数据已到达。

超时重传:发送方发送数据后启动定时器,若未收到确认则重发数据包。

复制代码
// 超时重传示意
发送端: 发送 seq=1 → 启动定时器
接收端: 收到数据 → 发送 ACK=2
发送端: 收到 ACK → 取消定时器

// 如果 ACK 丢失
发送端: 发送 seq=1 → 启动定时器
接收端: 收到数据 → 发送 ACK=2 (丢失)
发送端: 定时器超时 → 重传 seq=1

去重处理:通过报文序号识别并丢弃重复数据包。

乱序重排:根据序号重新排列到达顺序错乱的数据包。

三、滑动窗口机制

滑动窗口是TCP的流量控制机制,用于调节发送速率,防止接收方缓冲区溢出。

工作原理

  • 窗口内数据可一次性发送(无需等待单个确认)

  • 收到确认后窗口沿数据流方向滑动

  • 窗口大小决定允许发送的未确认数据量

四、TCP 与 UDP 协议对比

对比维度 TCP UDP
连接性 面向连接(三次握手) 无连接
可靠性 可靠(确认+重传) 不可靠(尽最大努力)
数据边界 流式(无边界) 数据报(有边界)
传输效率 较低 较高
适用场景 文件传输、网页访问 实时视频、DNS查询

选择依据

  • 需要数据完整性 → TCP(如文件下载)

  • 容忍丢包、要求低延迟 → UDP(如视频通话)


第二部分:TCP 连接状态机

一、状态总览

TCP连接从创建到关闭会经历多个状态变化,监控连接状态对排查网络问题至关重要。

状态 说明
CLOSED 假想的起始状态,实际代码中不可见
LISTEN 服务器监听状态,等待客户端连接
SYN_SENT 客户端发送SYN后进入的状态
SYN_RCVD 服务器收到SYN后进入的状态
ESTABLISHED 三次握手完成后进入的连接状态
FIN_WAIT_1 主动关闭方发送FIN后进入的状态
FIN_WAIT_2 收到ACK后进入的状态
CLOSE_WAIT 被动关闭方收到FIN后进入的状态
LAST_ACK 被动关闭方发送FIN后进入的状态
TIME_WAIT 主动关闭方完成四次挥手后进入的状态

二、状态观察方法

查看TCP连接状态

netstat -natp

输出示例

Proto Recv-Q Send-Q Local Address Foreign Address State

tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN

tcp 0 0 192.168.1.146:6000 192.168.1.100:54321 ESTABLISHED

tcp 0 0 192.168.1.146:6000 192.168.1.100:54322 TIME_WAIT

第三部分:TCP 三次握手

一、握手流程

详细说明

步骤 方向 报文内容 状态变化
1 客户端 → 服务器 SYN=1, seq=x 客户端进入 SYN_SENT
2 服务器 → 客户端 SYN=1, ACK=1, seq=y, ack=x+1 服务器进入 SYN_RCVD
3 客户端 → 服务器 ACK=1, ack=y+1 双方进入 ESTABLISHED

二、为什么不能是两次握手?

两次握手的缺陷:无法确认客户端存活状态。

// 攻击场景

客户端发送SYN → 立即退出

服务端回复SYN+ACK → 等待客户端ACK(永远不会到来)

服务端资源被占用,造成资源浪费

三次握手的必要性:第三次ACK确认双方状态同步,防止半开连接。

三、SYN Flood 攻击

攻击原理:攻击者发送大量伪造SYN包,占满服务器的未完成握手队列。

防御措施

  • SYN Cookie 技术

  • 识别异常IP进行限流

  • 防火墙检测同一IP的异常SYN报文频率


第四部分:TCP 四次挥手

一、挥手流程

二、为什么是四次挥手?

TCP是全双工通信,双方需要独立关闭自己的发送通道:

次数 发送方 报文 含义
1 主动方 FIN 主动方不再发送数据
2 被动方 ACK 确认收到关闭请求
3 被动方 FIN 被动方不再发送数据
4 主动方 ACK 确认关闭,进入TIME_WAIT

能否简化为三次?

  • 当被动方收到FIN后立即关闭连接时,可将FIN与ACK合并发送

  • 协议设计为四次是因为无法预知程序员何时调用close(),需要保持ACK的即时性

三、TIME_WAIT 状态详解

持续时间:2MSL(Maximum Segment Lifetime),通常约2分钟。

出现场景:仅出现在主动关闭连接的一端。

存在原因

原因 说明
可靠终止连接 确保最后一次ACK丢失时能处理重传的FIN报文。若直接关闭,对方重发FIN将收到RST响应导致错误
处理延迟报文 等待2MSL时间确保所有报文在网络中消失,防止旧连接的延迟报文被新连接误接收

实际影响

  • 端口处于被占用状态,无法立即重启相同端口的服务

  • 可通过设置SO_REUSEADDR套接字选项重用端口

cpp 复制代码
// 解决 TIME_WAIT 导致的端口占用问题
int opt = 1;
setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

第五部分:TCP 头部结构

TCP报文头部可同时携带序号和确认号字段,这是实现可靠传输的关键技术基础。

cpp 复制代码
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         源端口(16位)         |         目的端口(16位)        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                       序列号(32位)                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                     确认号(32位)                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据偏移 | 保留  |    标志位   |         窗口大小(16位)        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         校验和(16位)          |        紧急指针(16位)        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        选项(最多40字节)                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

关键标志位

标志位 含义
SYN 同步序列号,用于建立连接
ACK 确认号有效
FIN 发送方已无数据,请求关闭连接
RST 重置连接
PSH 立即推送数据

第六部分:拥塞控制

一、核心目标

提高网络利用率,降低丢包率,保证网络资源对每条数据流的公平性。

二、四个核心机制

机制 作用 触发条件
慢启动 指数增长发送窗口,探测网络容量 连接建立或检测到丢包
拥塞避免 线性增长窗口,防止网络过载 窗口达到慢启动阈值
快速重传 立即重传丢失报文段 收到3个重复ACK
快速恢复 温和降速,避免立即进入慢启动 快速重传后

三、慢启动机制

工作原理:初始cwnd=2-4SMSS,每RTT时间窗口大小翻倍。

发送轮次 拥塞窗口cwnd

1 1

2 2

3 4

4 8

5 16 ← 达到慢启动阈值,转为拥塞避免

类比说明:如同高速公路车流控制,逐步增加避免瞬间拥堵。

四、拥塞避免

达到慢启动阈值(ssthresh)后,采用加法增大策略:

  • 每收到一个ACK,cwnd增加1/cwnd

  • 每个RTT周期,cwnd增加1

五、快速重传与快速恢复

触发条件:收到3个重复ACK(表明有报文段丢失)。

快速重传:立即重传丢失报文段,不必等待超时计时器。

快速恢复

  • 将ssthresh设为当前cwnd的一半

  • cwnd设置为新的ssthresh(或ssthresh+3)

  • 进入拥塞避免阶段

cpp 复制代码
检测到丢包
     │
     ▼
ssthresh = cwnd ÷ 2
     │
     ▼
cwnd = ssthresh + 3(快速恢复)
     │
     ▼
进入拥塞避免阶段(线性增长)

六、AIMD 原则

策略 说明 阶段
加法增大 拥塞避免阶段的线性增长 拥塞避免
乘法减小 拥塞发生时窗口减半 快速恢复

第七部分:HTTP 协议基础

一、HTTP 请求方法

方法 含义 安全性 幂等性
GET 请求获取资源
POST 提交数据
HEAD 仅获取头部信息
PUT 上传资源
DELETE 删除资源
OPTIONS 查看支持的请求方法

二、HTTP 状态码分类

分类 含义 典型状态码
1xx 信息类 100 Continue
2xx 成功类 200 OK
3xx 重定向类 301 Moved, 302 Found, 304 Not Modified
4xx 客户端错误 400 Bad, 401 Unauthorized, 403 Forbidden, 404 Not Found
5xx 服务器错误 500 Internal, 503 Unavailable

三、HTTP 通信流程

cpp 复制代码
浏览器访问网页的过程:
1. DNS解析:将域名解析为IP地址
2. TCP三次握手:与服务器建立连接(默认端口80)
3. 发送HTTP请求:GET /index.html HTTP/1.1
4. 服务器响应:HTTP/1.1 200 OK
5. 浏览器渲染:呈现页面内容
6. TCP四次挥手:关闭连接(或保持持久连接)

知识小结

知识点 核心内容 难度
TCP协议特点 面向连接、可靠传输、流式服务 ⭐⭐⭐⭐
UDP协议特点 无连接、不可靠、数据包服务 ⭐⭐
三次握手 SYN→SYN+ACK→ACK ⭐⭐⭐
四次挥手 FIN→ACK→FIN→ACK ⭐⭐⭐⭐
TIME_WAIT 主动关闭方状态,持续2MSL ⭐⭐⭐⭐
滑动窗口 流量控制机制 ⭐⭐⭐⭐
拥塞控制 慢启动→拥塞避免→快速重传→快速恢复 ⭐⭐⭐⭐⭐
HTTP基础 GET/POST方法,状态码分类 ⭐⭐

本文详细讲解了TCP协议的核心机制:

  1. 可靠性实现:确认应答、超时重传、去重、乱序重排

  2. 状态机:从LISTEN到ESTABLISHED,再到TIME_WAIT的完整状态转换

  3. 三次握手与四次挥手:连接建立与关闭的完整流程

  4. TIME_WAIT状态:存在的两个原因及实际影响

  5. 拥塞控制:慢启动、拥塞避免、快速重传、快速恢复四大机制

这些知识点不仅是网络编程的基础,更是面试中的高频考点。理解TCP协议的底层工作原理,能够帮助你在实际开发中更好地排查网络问题、优化传输性能。

相关推荐
林熙蕾LXL1 小时前
系统调用&文件描述
linux·运维·服务器
落羽的落羽1 小时前
【网络】TCP与UDP协议使用指南,Socket编程实现Echo服务
linux·服务器·网络·c++·网络协议·tcp/ip·机器学习
草莓熊Lotso2 小时前
LangChain从入门到精通:环境搭建→核心能力→LCEL链式编程全实战
android·java·linux·服务器·langchain
GanGanGanGan_10 小时前
RustDesk 安装指南 — Rocky Linux 9 + XFCE X11
linux·运维·centos
风落无尘10 小时前
《智能重生:从垃圾堆到AI工程师》——第五章 代码与灵魂
服务器·网络·人工智能
其实防守也摸鱼13 小时前
CTF密码学综合教学指南--第九章
开发语言·网络·python·安全·网络安全·密码学·ctf
xlq2232214 小时前
50.UDP套接字
网络·网络协议·udp
南境十里·墨染春水14 小时前
linux学习笔记 网络编程——Socket入门与TCP客户端/服务器实现
linux·服务器·网络
qq_三哥啊15 小时前
【mitmproxy】通过 mitmproxy 的HTTP代理模式获取 OpenCode 发起的 AI API 请求的详细信息
网络·http·代理模式