TCP 核心问题 之 滑动窗口
本篇只聊一个问题,“滑动窗口”
名词统一:
之前的文章中,我会说 TCP 包,这里我们统一一下名词概念。
当我们仅聊 TCP 本身的机制时,我们称其为 TCP 报文段,也就是之前我所介绍的,仅指 TCP 这一部分。
对于 “包” 或者说 数据包 、网络包 ,这里我将其理解为更大的一层,也就是包含 TCP 报文段
网络层 IP 包 = IP 头 + TCP 报文段
(但是其实吧,包 和 报文段 怎么说都不能算错,都是一种结构的代指嘛)
你将了解
- 到底什么是 TCP 的滑动窗口
滑动窗口含义
在前几篇 TCP 协议头全解 、 TCP 核心问题剖析之 什么 TMD 是 “三次握手”、TCP 核心问题剖析之 “四次挥手”、TCP 核心问题 之 Keep-Alive 的抓包中,细心的同学可能观察到有 Win = 30336
这样一个数据,那这个值其实就是标识的滑动窗口的大小。
所谓 “滑动窗口” 其实就是数据接收方用于控制自身当前可处理接收数据量大小的一个数值,这也是 TCP 流量控制 的一部分。
也就是请求交互的双方要告诉对方,我目前还能处理数据的量是多少,你要按照我给定的这个量来控制发送数据的速度。
避免数据堆积,压力过大,历史数据石沉大海等问题。
那么如何来确定滑动窗口的大小呢? 接受数据端 和 发送数据端 会保存不同的数据结构来进行记录。
滑动窗口数据结构
对于发送端
有以下几个变量
SWS (Send Window Size): the upper bound on the number outstanding frames (not ACKed) the sender can transmit
发送窗口大小 :发送方可以传输的未完成报文段的上限 (这里未完成是指没有被确认的,即未收到 ack 回复的报文段)
LAR (Last ACK Received): the sequence number of the last ACK received
最后已收到 ACK:最后收到 ACK 的序列号
LFS (Last Frame Sent): the sequence number of the last frame sent
最后发送报文段:最后发送报文段的序列号
所以有这样一个关系
LFS - LAR <= SWS
所以一个包的 ACK 都会使得 --> LAR 右移一位 --> 进而发送方可以多发一个报文段。
SWS 发送窗口大小取决于当前 接受端 接收缓冲区的大小,该值由接收方动态控制调整。
对于接收端
RWS (Receiver window size):the upper bound on the number of out-of-order frames the receiver is willing to accept
接收者窗口大小:接收端愿意接收的无序的报文段的上限
LAF (Largest acceptable frame):the sequence number of the largest acceptable frame
最大可接受报文段:最大可接收报文段的序列号
LFR (Last frame received):the sequence number of the last frame received
最后已接收报文段: 最后已接收报文段序列号
当一个报文段到来的时候,判断 SeqNum
if(SeqNum <= LFR || SeqNum >LAF) than 因为超出了窗口所以抛弃该报文段
if(LFR < SeqNum <= LAF) than 改报文段被接受
接收端 ACK 的机制
接收端接收到具有 SeqNum 的报文段并符合接受条件,将更新 SeqNumToAck 并设置
LFR (最后已接收报文序号)= SeqNumToAck
LAF (最大可接收报文号)= LFR + RWS (滑动窗口大小)
SeqNumToAck: 没有被 ack 的最大的序列号,也就是说所有收到的报文段 <= SeqNumToAck
TCP 的 Sliding Windows 滑动窗口(这里指发送端)作用
- 保证数据的可靠交付
- 确保数据有序交付
- 在发送端和接收端实行流量控制 flow control
- 想法是,发送端不会超出接受端的 buffer 缓冲区
Receiver’s Advertised Window 接收端的滑动窗口
- 接收端的滑动窗口大小是不固定的
- 接收端可动态调整窗口大小
- 发送方在任何时候都将被限制,不会有超过 Advertised Window 大小的未被确认的数据。