当前位置: 首页 > news >正文

TCP, 三次握手, 四次挥手, 滑动窗口, 快速重传, 拥塞控制, 半连接队列, RST, SYN, ACK

目录

  • TCP 是什么:面向连接 + 可靠 + 字节流
  • 三次握手:为什么不是两次
  • 四次挥手与 TIME_WAIT:谁等谁
  • 序列号/确认号与去重、排序、确认
  • 重传机制:超时重传与快速重传
  • 滑动窗口与流量控制
  • 拥塞控制:慢启动/拥塞避免/快重传/快恢复
  • 保活机制与长连接
  • 半连接队列、全连接队列与 SYN 攻击
  • RST 的语义:什么时候会被动断开
  • 常见高频面试问答(含易错点)
  • 抓包与排错清单
  • 参考与延伸阅读

在这里插入图片描述

TCP 是什么:面向连接 + 可靠 + 字节流

  • 面向连接:通信前需要建立连接(三次握手)。
  • 可靠交付:通过序列号、确认号、校验和、重传、窗口等保证不丢、不重、按序到达(应用层“看起来”按序)。
  • 字节流:没有消息边界,数据是连续字节流,分段与拼包在传输层完成。

简图(字节流与按序):

[App 写入字节] => [TCP 分段 seq=100..] => [网络] => [TCP 重组、去重、排序] => [App 读到连续字节]

三次握手:为什么不是两次

三次握手的目标:

  • 交换初始序列号(ISN)并建立双向通信能力。
  • 让客户端和服务端都“确认”对方的收发能力都正常。

流程(简化):

CLOSE -> SYN-SENT --SYN(x)--> LISTEN
SYN-RCVD <--SYN(y),ACK(x+1)-- LISTEN
ESTABLISHED --ACK(y+1)--> ESTABLISHED

为什么不能两次?

  • 若两次握手,服务端无法判断当前请求是否“历史连接”重放;第三次 ACK 让客户端基于上下文确认“我确实与这个服务端建立了当前连接”,避免“僵尸连接”占用资源。

我常用的比喻:

  • 第一次:我能发(SYN)。
  • 第二次:我能收能发(SYN+ACK)。
  • 第三次:我也能收(ACK),双方都齐活。

注:半连接队列记录“收到 SYN 尚未完成握手”的请求;若第三次 ACK 不到,条目会因超时被清理。


四次挥手与 TIME_WAIT:谁等谁

为什么“挥手”通常是四次?

  • 关闭是“单向”的:一方 FIN 只表示“我不再发了”,对方读到 FIN 但仍可继续发送,故需要两对报文确保双方各自完成“发送通道”的关闭。

典型序列:

(主动关闭)  FIN -> ACK    (被动方进 CLOSE_WAIT)...对方数据发送完...FIN -> ACK    (主动方进 TIME_WAIT)

TIME_WAIT 的意义:

  • 等 2MSL,确保:
    • 最后的 ACK 若丢失,对方重发 FIN,我还能重发 ACK;
    • 旧连接的迟到报文不会影响未来新的同四元组连接。

调优提示:

  • 服务端侧可让“短连接风格”的一方尽量成为被动关闭者,降低其 TIME_WAIT 压力(视业务/栈实现)。

序列号/确认号与去重、排序、确认

我面试常用“翻书”比喻:

能力解决的问题类比
序列号(seq)去重与排序页码防重排
确认号(ack)成功到达的确认勾选“已读”
窗口(win)节流与并行度读写节拍

发送端维护已发送未确认的数据集合,接收端通过累计 ACK 告知“我已经连续收到哪一位点前的所有字节”。


重传机制:超时重传与快速重传

  • 超时重传(RTO):发送后启动定时器,超时无 ACK 则重发;RTO 自适应基于 RTT 与抖动(通常 > RTT 的一定倍数)。
  • 快速重传:收到 3 个重复 ACK(如 ACK=101,101,101),判定某段可能丢了,提前重传,减少等待 RTO 的成本。

要点:

  • 重传报文的 seq 与原始相同,可能合并为更大段(取决于实现)。
  • 局部乱序也会触发重复 ACK,但不等同于丢包;拥塞控制会进一步介入(见下)。

滑动窗口与流量控制

  • 接收窗口(rwnd):接收端缓冲可用空间,通过报文通告给发送端,防止“接收方处理不过来”。
  • 发送窗口(swnd):发送端根据 min(cwnd, rwnd) 决定实际并发在途数据量。
  • 零窗口探测:若 rwnd=0,发送端定期发探测报文,等待窗口开放。

可视化(简略):

|--- 已确认 ---|--- 已发送未确 ---|--- 可发送窗口 ---|^ base            ^ nextSeq

拥塞控制:慢启动/拥塞避免/快重传/快恢复

  • cwnd:拥塞窗口,代表“网络可能承受的并发在途量”的猜测值。
  • 慢启动:从 1 MSS 开始指数增长,阈值 ssthresh 之前翻倍,之后线性增加(拥塞避免)。
  • 快重传/快恢复:
    • 3 次重复 ACK 触发:ssthresh = cwnd/2cwnd = ssthreshssthresh + 3*MSS(依实现),进入快速恢复,避免回到 1 MSS 的冷启动。
  • 超时:说明更严重拥塞,通常将 cwnd 置 1 MSS,重新慢启动。

保活机制与长连接

  • KeepAlive:长时间无数据时周期性发送探测包;若多次无响应,判定连接死亡并关闭。默认关/开与探测周期依 OS 而异,可配置。
  • 应用层心跳:例如 HTTP/2、WebSocket 自带 ping/pong,更灵活。

半连接队列、全连接队列与 SYN 攻击

  • 半连接队列(SYN 队列):收到 SYN,发送 SYN+ACK,等待第三次握手的 ACK。若超时未到达则过期剔除。
  • 全连接队列(Accept 队列):三次握手完成的连接,等待应用层 accept() 取走。
  • 防护思路:
    • SYN Cookies、缩短 SYN/ACK 重传与过期时间、增大队列。
    • 使用负载均衡/防火墙清洗异常 SYN 洪泛。

RST 的语义:什么时候会被动断开

  • RST 表示“连接非法/不存在或异常状态”,常见触发:
    • 目标端口无进程监听;
    • 应用层提前关闭 socket,仍收到对端数据;
    • 抓包/半开异常导致状态机不同步。
  • 面试提示:用 RST 终止连接不会进入 TIME_WAIT(与 FIN 流程不同)。

常见高频面试问答(含易错点)

  1. 为什么是三次握手不是两次?
  • 需要确认“双方收发能力”,并防历史连接的重放,占用资源。
  1. 为什么挥手要四次?
  • 关闭是单向的,两个方向分别 FIN/ACK。
  1. TIME_WAIT 为什么在主动关闭方?
  • 负责兜住最后 ACK 丢失与旧报文消散。
  1. 3 个重复 ACK 一定是丢包吗?
  • 不一定,可能乱序;但为降低时延会触发快速重传并调整拥塞窗口。
  1. rwndcwnd 谁说了算?
  • 实际可发窗口取两者较小值:min(cwnd, rwnd)
  1. 半连接队列爆了怎么办?
  • 开启 SYN Cookies、调大队列、缩短重试、前置抗 DDoS。
  1. 为什么 TCP 是字节流,UDP 是报文?
  • TCP 为可靠按序的连续字节,UDP 不保证顺序、丢失可见,保留消息边界。

抓包与排错清单

  • 观察三次握手:过滤 tcp.flags.syn==1 && tcp.flags.ack==0
  • 快速重传:看是否出现 3 次重复 ACK 与 Dup ACK 标记。
  • RTO 触发:同一 seq 的报文重发,时间间隔接近 RTO。
  • 零窗口:Window Size Value = 0 与周期性探测包。
  • 拥塞事件:[TCP Previous segment not captured][Retransmission]、窗口骤降。

Wireshark 过滤示例:

# 仅看 TCP 握手
tcp.flags.syn==1 || tcp.flags.fin==1 || tcp.flags.reset==1
# 指定四元组
ip.addr==A && ip.addr==B && tcp.port in {PORT1,PORT2}

参考与延伸阅读

  • RFC 793、RFC 5681:TCP 规范与拥塞控制
  • 《Linux高性能服务器编程》《TCP/IP 详解 卷一》
  • Wireshark 官方文档与实践


文章转载自:

http://RMQh2cVI.qtzwh.cn
http://EBT2CXsz.qtzwh.cn
http://KBgJt2xn.qtzwh.cn
http://r3zF5iX3.qtzwh.cn
http://kT1dq4pM.qtzwh.cn
http://Qk7e1K1l.qtzwh.cn
http://ix7VNw4x.qtzwh.cn
http://QwGqsP5a.qtzwh.cn
http://UuKANzGd.qtzwh.cn
http://hYB8UqAS.qtzwh.cn
http://MD4UdFEa.qtzwh.cn
http://tygyVcdo.qtzwh.cn
http://kbAOsLgb.qtzwh.cn
http://ZEOJUueu.qtzwh.cn
http://GL7hq2Gh.qtzwh.cn
http://h7Q14Xez.qtzwh.cn
http://Hwkeeweg.qtzwh.cn
http://RSE9Gmmt.qtzwh.cn
http://khnWLdxu.qtzwh.cn
http://ozLS0f0e.qtzwh.cn
http://ueptGOnx.qtzwh.cn
http://jWvYcngF.qtzwh.cn
http://bkcBizGZ.qtzwh.cn
http://oUxzR32H.qtzwh.cn
http://vF5I7L3t.qtzwh.cn
http://WepWosIi.qtzwh.cn
http://Rvv4hovc.qtzwh.cn
http://exmgnuYD.qtzwh.cn
http://7SxDOLqr.qtzwh.cn
http://CEe9g1Pg.qtzwh.cn
http://www.dtcms.com/a/371399.html

相关文章:

  • Ansible 角色(Roles)
  • 深入理解 X25519 与 Ed25519:密钥交换与签名验签全流程解析
  • 【Python】数据可视化之热力图
  • 分布式专题——2 深入理解Redis线程模型
  • 【xss漏洞waf绕过】
  • Next.js中静态资源处理:图片、字体和其他文件
  • PyCharm 从入门到高效:安装教程 + 快捷键速查表
  • Linux 之从硬件硬盘到文件系统的全面过渡
  • STM32的USART的数据寄存器只有一个吗?
  • 【RabbitMQ】---RabbitMQ 工作流程和 web 界面介绍
  • HakcMyVM-Literal
  • C++判断字符串是否是回文(palindrome)
  • 测试:BUG篇
  • web后端知识(php和python)——第一阶段
  • 安卓学习 之 ProgressBar(进度条)控件
  • Python操作MySQL的两种姿势:原生SQL与ORM框架SQLAlchemy详解
  • TypeScript 核心语法与 Vue2 指令知识点
  • Java 14 开箱,新特性Record、instanceof、switch香香香香
  • HarmonyOS 应用开发新范式:深入探索 Stage 模型与 ArkUI 声明式开发
  • 跳转原生系统设置插件 支持安卓/iOS/鸿蒙UTS组件
  • 5-2EFCore性能优化
  • 《sklearn机器学习——管道和复合估计器》联合特征(FeatureUnion)
  • 大数据毕业设计选题推荐-基于大数据的贵州茅台股票数据分析系统-Spark-Hadoop-Bigdata
  • C++ 容器——unordered_xxx
  • 常见设计模式详解
  • 网络爬虫(web crawler)
  • 319章:使用Scrapy框架构建分布式爬虫
  • (LeetCode 面试经典 150 题) 67. 二进制求和(位运算、字符串)
  • 【linux kernel 常用数据结构和设计模式】【数据结构 3】【模拟input子系统input_dev和input_handler之间的多对多关系】
  • 怎么用CXL加速数据库?· SIGMOD‘25