关键词搜索

源码搜索 ×
×

互联网协议 — TCP — 滑动窗口

发布2023-04-09浏览8157次

详情内容

目录

TCP ARQ 协议

ARQ(Automatic Repeat Request,自动重传请求)是一种错误控制技术,在 TCP 协议中,TCP ARQ 通过 “ACK 确认“ 和 “超时重传“ 来保证数据传输的可靠性和有序性。

TCP ARQ 主要有以下 2 大类实现:

  1. Stop-And-Wait ARQ(停止并等待 ARQ)协议:Sender 必须等待 Receiver 的 ACK 之后再继续发送 REQ。
    在这里插入图片描述

  2. Continuous ARQ(连续 ARQ)协议:Sender 不必等待 Receiver 的 ACK,所以支持批量发送 REQ。
    在这里插入图片描述

在 Linux 中主要实现了 Continuous ARQ 协议,又可以细分为 2 种模式:

  1. Go-Back-N(回退 N 重传)ARQ:由超时重传、快速重传、滑动窗口共同支撑实现。

  2. Selective Repeat(选择重传)ARQ:是对 Go-Back-N 的改进,引入了 SACK,解决了 Go-Back-N 存在的错序、丢包等问题。

在这里插入图片描述

TCP 的滑动窗口

上述可知,如果要实现 Continuous ARQ,还需要滑动窗口机制。核心作用有两个:

  1. 用于控制 Sender 发送数据的速率,避免 Sender 发送的速率超出 Receiver 的处理能力,从而导致网络拥塞。
  2. 用于支持 Sender 批量发送数据,而不必每个 Segment 都要等待 Receiver 的 ACK,从而提高效率。

TCP 滑动窗口(Sliding Window)的实现依赖 TCP Header 的 Window Size 字段,Receiver 以此来向 Sender 宣告自己当前的接口窗口大小,可见窗口大小是由 Receiver 决定的。结合实际网络情况,可以动态的进行调整。

  • 当网络拥塞时,Receiver 告知 Sender 慢点发。
  • 当网络顺畅时,Receiver 告知 Sender 快点发。

Sender 滑动窗口

滑动窗口在 Kernel 中体现为一个 Segments 收发缓冲空间。

假设目前的 Sender 滑动窗口的缓冲空间如下分布:

  1. 释放区:存放已发送,并收到 ACK 的 Segments(1~31Byte),会被逐个释放。
  2. 发送区:包括发送窗口(蓝色)和可用窗口(紫色)。
    1. 发送窗口:存放已发送,但未收到 ACK 的 Segments(32~45Byte),继续等待 ACK。
    2. 可用窗口:存放未发送,但属于 Receiver 可处理范围的空间(46~51Byte),等待发送。
  3. 缓存区:存放未发送,但超出了 Receiver 可处理范围的空间(51Byte~),暂不发送。

在这里插入图片描述

  1. 当 Sender 把 “可用窗口“ 的 Segments 全部都发送出去后,大小就变为 0 了,表示 “可用窗口“ 耗尽。Sender 在没收到新的 ACK 确认之前,不会再继续发送。
    在这里插入图片描述

  2. 当 “发送窗口“ 中 32-36Byte 的 Segments 收到了 ACK 后,空间划入释放区(#1),如果此时 “发送窗口” 的大小没有被动态调整,那么此时 “发送窗口” 向前滑动 5Byte,且划分为新的 “可用窗口",表示 Sender 可以继续发送新的 Segments。

在这里插入图片描述

Kernel TCP 协议的 Sender 滑动窗口实现如下:

  1. SND.UNA:指向发送窗口的入口地址。
  2. SND.WND:表示发送窗口的大小,与 Receiver 协商确定;
  3. SND.NXT:指向可用窗口的入口地址。

那么,可用窗口大小的计算公式为:

可用窗口大小 = SND.WND -(SND.NXT - SND.UNA)

    在这里插入图片描述

    Receiver 滑动窗口

    Receiver 滑动窗口的缓冲区分布如下图所示。

    1. 确认区:存放已接受,且已返回 ACK 的 Segments,等待 read() 读取。
    2. 接收区(接收窗口):存放待接收的 Segments,表示 Receiver 目前的处理能力。
    3. 缓存区:保留空间。

    Kernel TCP 协议的 Receiver 滑动窗口实现如下:

    1. RCV.NXT:指向接收窗口的入口地址。
    2. RCV.WND:表示接收窗口的大小,会通告给 Sender。

    在这里插入图片描述

    滑动窗口处理流程

    在这里插入图片描述

    窗口探测

    实际上,Sender 除了被动地从 Receiver 返回的 ACK 中获悉窗口大小之外,Kernel TCP 协议还实现了一个 Timer(定时器),用于周期性发送窗口探测(Window Probe)报文,继而主动获悉此时的窗口大小。

    窗口探测机制是为了预防复杂网络中出现的某些特殊情况而设计的,例如:窗口开关问题。

    • 窗口关闭,即:一种情况时,当 Receiver 的接收窗口为 0 时,会 ACK 一个 Window Size = 0 给 Sender,指示 Sender 不要再发送数据了;
    • 窗口开启,即:窗口关闭后,Receiver 在某一时刻返回了 Window Size != 0 的 ACK 给 Sender,指示 Sender 可以继续发送数据了。

    在上述两情况中,这个用于开关窗口的 ACK 都至关重要,如果丢失就会导致很坏的结果,比如 S/R 双方陷入死锁。

    在这里插入图片描述

    基于 TCP 窗口探测(Window Probe)报文可以很好的解决上述问题。

    • 如果接收窗口仍然为 0,那么 Sender 重启 Timer。
    • 如果接收窗口不再为 0,那么 Sender 开始发送数据。

    在这里插入图片描述

    相关技术文章

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载