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

TCP小结 - 指南

TCP小结 - 指南

1. 核心特性

面向连接:通过三次握手建立连接,四次挥手终止连接,确保通信双方状态同步。

TCP连接建立的3次握手

抓包:

client发出连接请求;

server回应client请求,并且同步发送syn连接;

client回应连接,至此3步握手完成。

TCP连接释放的4次握手

Client:192.168.2.100 -- server:192.168.2.101之间的TCP 4次挥手(释放连接)

client主动断开连接

 server确认断开,server主动断开,client确认断开。

可靠性传输:通过序列号、确认应答(ACK)、超时重传、重复ACK检测等机制保证数据完整有序。

序列号、确认应答(ACK):

超时重传

重复ACK

全双工通信:双方可同时发送和接收数据。

字节流服务:数据被拆分为TCP段传输,接收方按序重组为连续字节流。

流量控制:通过滑动窗口机制动态调整发送速率,避免接收方缓冲区溢出。

TCP窗口就是什么

TCP 采用流量控制(Flow Control)机制,使用滑动窗口(Sliding Window)来管理数据的发送和接收。

TCP 头部中的 窗口大小字段(Window Size) 指定了接收方当前可以接受的最大数据量,用于控制数据流,以防止接收方被发送方淹没。

窗口大小字段(16 位)最大能表示的值是 65,535(2¹⁶ - 1)字节,即约 64 KB,这个值在现代高速网络环境下严重不足,因此 TCP 提供了Window Scale 选项来扩展窗口大小

Window Scale选项的作用

Window Scale(窗口缩放)选项用于扩展 TCP 窗口的大小,使其支持最大 1GB(2³⁰ 字节)的窗口,而不是 64KB。

在 TCP 头部,窗口大小字段 只有 16 位,最大值为 65,535 字节(64KB)。

但是,高带宽-时延(BDP,Bandwidth Delay Product)网络环境下,64KB 可能会严重限制吞吐量。

Window Scale 选项通过左移窗口大小字段,扩展了窗口的范围,最大可达 1GB

Window Scale 选项的工作原理

TCP 窗口扩展通过一个"缩放因子"(Scaling Factor)来扩大窗口的大小:

Window Scale 选项定义了一个因子 n(0 ≤ n ≤ 14),窗口大小的计算方式变为:

实际窗口大小=TCP 头部窗口大小字段×2^n(2的n次方)

其中:

   TCP 头部的窗口字段(Window Size) 仍然存储 16 位的值(最大 65,535)。

   缩放因子 n 在 Window Scale 选项中存储,范围是 0 到 14。

   最终的实际窗口大小最大可达 65,535 × 2¹⁴ = 1,073,725,440 字节(即 1GB)。

Window Scale 选项的格式

Kind    Length  Shift Count

+------+--------+-------------+

|  3     |   3      |     n         |

+------+--------+-------------+

字段解释:

Kind = 3:表示这是 Window Scale 选项。

Length = 3:整个字段占用 3 字节。

Shift Count:即缩放因子 n,接收方必须用 2^n 进行窗口扩展计算。

Window Scale 选项的协商(在 TCP 三次握手时)

Window Scale 选项只能在 TCP 三次握手期间协商,后续不能更改。

双方都必须在 SYN 报文中发送 Window Scale 选项,否则不会启用。

每一方独立协商自己的窗口缩放因子。

Tcp连接第一次握手协商win-mss-ws

Tcp连接第二次握手协商win-mss-ws

Tcp连接第三次握手协商win

TCP发送窗口和接收窗口

拥塞控制:通过慢启动、拥塞避免、快速重传/恢复等算法避免网络过载。

慢启动(Slow Start)

初始拥塞窗口(cwnd)较小,每收到一个ACK,cwnd指数增长(如1, 2, 4, 8...)。

达到阈值(ssthresh)后进入拥塞避免阶段。

拥塞避免

cwnd线性增长(如每RTT增加1),避免激进发送。

飞快重传与快速恢复

检测到3个重复ACK时,立即重传丢失包,并设置ssthresh = cwnd/2, cwnd = ssthresh + 3,进入敏捷恢复阶段。

超时重传(拥塞处理)

超时表明严重拥塞,重置ssthresh = cwnd/2, cwnd = 1,重新慢启动。

1、慢启动;慢启动的算法:当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1。(慢启动呈指数增加)

这里假定拥塞窗口 cwnd 和发送窗口 swnd 相等,下面举个栗子:

连接建立完成后,一开始初始化 cwnd = 1,表示可以传一个 MSS 大小的数据。

当收到一个 ACK 确认应答后,cwnd 增加 1,于是一次能够发送 2 个

当收到 2 个的 ACK 确认应答后, cwnd 增加 2,于是就可以比之前多发2 个,因此这一次能够发送 4 个

就可以比之前多发 4 个,所以这一次能够发送 8 个。可以看出慢启动算法,就是当这 4 个的 ACK 确认到来的时候,每个确认 cwnd 增加 1, 4 个确认 cwnd 增加 4,于发包的个数是指数性的增长

那慢启动涨到什么时候是个头呢?

有一个叫慢启动门限  ssthresh (slow start threshold)状态变量。

当 cwnd(拥塞窗口) < ssthresh 时,使用慢启动算法。

当 cwnd(拥塞窗口) >= ssthresh 时,就会利用「拥塞避免算法」。

2、拥塞避免:每当收到一个 ACK 时,cwnd 增加 1/cwnd。就是;进入拥塞避免算法后,它的规则(拥塞避免线性增长),当触发了重传机制,也就进入了「拥塞发生算法」。

前面说道,当拥塞窗口 cwnd 「超过」慢启动门限 ssthresh 就会进入拥塞避免算法。

一般来说 ssthresh 的大小是 65535 字节。

那么进入拥塞避免算法后,它的规则是:每当收到一个 ACK 时,cwnd 增加 1/cwnd。

接上前面的慢启动的例子,现假定 ssthresh 为 8:当 8 个 ACK 应答确认到来时,每个确认增加 1/8,8 个 ACK 确认 cwnd 一共增加 1,于是这一次能够发送 9 个 MSS 大小的数据,变成了线性增长。

就会出现丢包现象,这时就需要对丢失的数据包进行重传。就是就这么一直增长着后,网络就会慢慢进入了拥塞的状况了,于

当触发了重传机制,也就进入了「拥塞发生算法」。

3、拥塞发生

当网络出现拥塞,也就是会发生数据包重传,重传机制首要有两种:超时重传、快速重传

当发生了「超时重传」,就会使用拥塞发生算法。

这个时候,Ssthresh(慢启动门限) 和 cwnd(拥塞窗口) 的值会发生变化:

ssthresh 设为 cwnd/2(慢启动门限设置为当前拥塞窗口的1/2),

cwnd 重置为 1(是恢复为 cwnd 初始化值,我这里假定 cwnd 初始化值 1),

接着,就重新开始慢启动,慢启动是会突然减少数据流的。这真是一旦「超时重传」,马上回到解放前。但是这种方式太激进了,反应也很强烈,会造成网络卡顿。

发生快速重传拥塞发生算法

飞快重传算法:当接收方发现丢了一个中间包的时候,发送三次前一个包的 ACK,于是发送端就会迅速地重传,不必等待超时再重传。

TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,则 ssthresh 和 cwnd 变化如下:

cwnd(拥塞窗口) = cwnd/2 ,也就是设置为原来的一半;

ssthresh(慢启动门限) = cwnd;

进入快捷恢复算法。

4、快速恢复

高效恢复算法是认为,你还能收到 3 个重复 ACK 说明网络也不那么糟糕,所以没有必要像 RTO 超时那么强烈。

进入快速恢复之前,cwnd 和 ssthresh 已被更新了:

cwnd = cwnd/2 ,也就是设置为原来的一半;

ssthresh = cwnd;

进入高效恢复算法如下:

1.拥塞窗口 cwnd = ssthresh + 3 ( 3 的意思是确认有 3 个数据包被收到了);

2.重传丢失的数据包;

3.如果再收到重复的 ACK,那么 cwnd 增加 1;

4.如果收到新数据的 ACK 后,把 cwnd 设置为第一步中的 ssthresh 的值,原因是该 ACK 确认了新的内容,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态;

2. 抓包分析技巧

Wireshark过滤:

  tcp.analysis.retransmission:定位重传包。

  tcp.analysis.window_update:观察窗口变化。

  tcp.options.sack:分析SACK块范围。

关键指标:

  重传率 = 重传包数 / 总包数(>1%需告警)。

  乱序深度:连续Out-Of-Order包数量。

  RTT波动:标准差反映网络稳定性。

http://www.hskmm.com/?act=detail&tid=25441

相关文章:

  • 国庆 Day2 强基物理
  • ZR 2025 十一集训 Day 6
  • 软件版悟空博弈 + WAUC:构筑元人文的演化之路
  • 基于MVO多元宇宙优化的DBSCAN聚类算法matlab仿真
  • AirSim 安装过程记录 - zzh
  • LARAVEL安装报错:Illuminate\Database\QueryException could not find driver (Connection: sqlite, SQL:
  • 基于AXI模块的视频流传输(硬件连接篇)
  • [GDOUCTF 2023]泄露的伪装
  • 仿射密码
  • AtCoder Regular Contest 207 (Div.1) 游记
  • 深入解析:AI破局:饿了么如何搅动即时零售江湖
  • 从零开始学Flink:数据输出的终极指南
  • 数据编织平台实现AI代理自助数据访问
  • [题解]P12008 【MX-X10-T4】[LSOT-4] Fragment of Memories
  • 线性表的顺序存储和链式存储
  • AWS WebRTC:获取ICE服务地址(part 3):STUN服务和TURN服务的作用 - 实践
  • Python中的对象池与驻留机制:小整数、字符串与大整数
  • 基于ADMM无穷范数检测算法的MIMO通信系统信号检测MATLAB仿真,对比ML,MMSE,ZF以及LAMA
  • 点乘与叉乘的由来:从四元数到公理自洽的启示
  • 【算法深练】分组循环:“分”出条理,化繁为简 - 教程
  • java学习日记10.5
  • 【JNI】JNI基础语法
  • 【EF Core】通过 DbContext 选项扩展框架
  • 从Chrome渲染器代码执行到内核:MSG_OOB漏洞分析与利用
  • assistant-ui
  • 20251006 之所思 - 人生如梦
  • C# Avalonia 16- Animation- RotateButton
  • 2025 十一集训
  • 汇编实验3
  • 20251005 模拟测 总结