网络:TCP序列号和滑动窗口,顺序保证

TCP通过序列号(Sequence Number) 和滑动窗口(Sliding Window) 两大核心机制保证数据顺序,同时实现高吞吐量。以下从原理到实践逐步解析:

一、顺序保证的核心:序列号与确认号

1. 字节流编号

  • 发送序列号(SEQ):每个TCP段携带的序列号 = 该段第一个字节在数据流中的全局位置
    (如首段SEQ=1000,携带100字节 → 下一段SEQ=1100)
  • 确认号(ACK):接收方回复的ACK = 期望接收的下一个字节的序列号
    (收到SEQ=1000的段后,回复ACK=1100)

2. 顺序控制流程

  • 乱序处理:若段2(SEQ=1200)比段1先到达:
    • 接收方发现SEQ=1200不连续(期望1000) → 缓存段2但不确认
    • 收到段1(SEQ=1000)后 → 连续确认至1400(段1+段2)

✅ 关键点:接收方只按序确认连续数据,乱序数据暂存缓冲区。

二、滑动窗口:平衡顺序与吞吐量

1. 窗口定义

  • 接收窗口(rwnd):接收方通告的剩余缓冲区大小(决定发送方可发多少数据)
  • 拥塞窗口(cwnd):发送方根据网络拥塞估算的最大在途数据量
  • 实际发送窗口 = min(rwnd, cwnd)

2. 滑动过程示例

  • 初始状态:
    • 发送窗口 = 3段(假设每段200字节)
    • 发送:段1(1000-1199)、段2(1200-1399)、段3(1400-1599)
  • 接收方确认段1:
    • 窗口右移 → 可发送段4(1600-1799)
  • 结果:
    • 顺序性:段1确认前,段4不会发送
    • 高吞吐:管道中始终有3个段在传输(并行)

3. 动态窗口调整

  • 接收方控制(rwnd):
    通过TCP头部的Window Size字段动态通告剩余缓冲区(如初始16KB → 降至8KB时限制发送速率)。
  • 拥塞控制(cwnd):
    • 慢启动:cwnd从1开始指数增长(1→2→4→8...)
    • 拥塞避免:接近阈值时线性增长(+1/cwnd per ACK)
    • 快速恢复:丢包时cwnd减半,避免连接重置

三、粘包/拆包与滑动窗口的关联

1. 粘包(Nagle算法)

  • 问题:小数据包(如SSH按键)频繁发送 → 浪费带宽(40字节头+1字节数据)
  • 解决:
    • 发送方缓存小数据,直到满足:
      a) 数据量 ≥ MSS
      b) 收到前一个包的ACK
    • 副作用:延迟增加(如游戏操作卡顿)
    • 禁用方法:setsockopt(TCP_NODELAY)

2. 拆包(MTU限制)

  • 强制拆包:应用层数据 > MSS → TCP自动拆分为多个段
  • 接收重组:接收方按SEQ号重组字节流,保证顺序透明

📌 关键结论:粘包是发送优化策略,拆包是传输层物理约束,二者均不影响接收端顺序。

四、如何追求更高吞吐量?

1. 窗口缩放(Window Scaling)

问题:TCP头部Window Size字段仅16位 → 最大窗口64KB(10Gbps链路下延迟>5ms即受限)

解决:握手时协商缩放因子(Scale Factor)

bash 复制代码
    # Linux查看窗口缩放
  cat /proc/sys/net/ipv4/tcp_window_scaling  # 默认1
  sysctl -w net.ipv4.tcp_window_scaling=3    # 缩放因子8(64KB*8=512KB)

2. 选择性确认(SACK)

问题:单个包丢失导致整个窗口重传(性能低下)

解决:接收方通告乱序接收的段范围

python 复制代码
    # SACK格式示例(TCP选项)
  TCP Header:
    Options: SACK=1200-1399, 1600-1799  # 收到段2和段4,但段3丢失

发送方仅重传段3(SEQ=1400-1599)

3. 高速网络优化

BBR算法:Google提出,通过测量带宽和延迟动态调整cwnd

bash 复制代码
    # Linux启用BBR
  sysctl -w net.ipv4.tcp_congestion_control=bbr

效果:YouTube平均吞吐提升4%,延迟降20%

总结

1. 顺序保证:

  • 序列号(SEQ)标记字节位置
  • 接收方按序确认(ACK)

2. 吞吐优化:

  • 滑动窗口控制管道数据量
  • 动态调整(rwnd/cwnd)适配网络状态

3.高级机制:

  • 窗口缩放突破64KB限制
  • SACK减少重传开销
  • BBR等算法智能避堵

滑动窗口的精髓在于:**以顺序性为前提,通过管道并行化最大化吞吐。**理解这一平衡艺术,是掌握TCP协议的关键所在。

相关推荐
blasit4 小时前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
BingoGo1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
DianSan_ERP5 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet