老青菜

TCP Sliding Window

2019-06-02

TCP协议栈支持全双工数据传递,可以同时发送和接收。那么他是如何保证可靠性?如何解决丢包、乱序等问题的呢?

An Unreliable Protocol

我们先来看不可靠协议的传输机制,比如说网络层IP协议,它是不可靠的,尽管有ICMP(控制消息协议),但是没有ACK,任然是不可靠的。

如上图所示,每一条消息发出去之后,并不知道对方有没有收到。

Positive Acknowledgment with Retransmission

为了保证消息准确到达,出现了 PAR机制,也就是带重传的肯定确认机制。

如上图所示,每一条消息发出去之后,我们启动一个计时器,等待对方告诉我们是否收到这条消息了。如果超时了,则进行重传。优缺点也很明显:

  1. 这样保证了传输可靠和顺序,适合数据交换频率低的场景。

  2. 缺点也很明显,效率不是很高,单位时间内的网络吞吐量比较低。

Enhanced Positive Acknowledgment with Retransmission

增强版的PAR 机制解决了普通PAR机制的效率问题,同时保证了传输的可靠性。主要有以下优化点:

  1. 增加了消息索引,一次可以发多条消息,每条消息单独确认;
  2. 保留了消息的计时器;
  3. 增加窗口机制,接收的负载,控制发送方的频率;

如上图所示,发送方可以发送多条消息,每一条消息启动一个计时器,等待消息的ACK。如果超时了,则进行重传;每一条消息会有一个窗口Limit参数,如果超过这个大小,发送方就不能继续发送。需要等待已发消息的ACK,也就是等待接收方处理完消息。

Sliding Window System

和增强版的 PAR 类似,TCP引入了 Sliding Window System 滑动窗口系统,实际上比前者要复杂很多。主要有以下更新:

  1. 增加了Window参数,表示剩余可接受的窗口大小。

  2. 增加了Seq(已发送的字节数)和Ack(已接收的字节数)。

发送窗口

因为TCP协议支持全双工的,那么有发送和接收这两个块缓冲区。我们先看发送的缓冲区:

我们来介绍下关键的几个名词:

1. Send Window
发送窗口,包含已发送待确认的窗口、未发送接收方准备好接收的窗口。

2. Already Sent Window
已发送的窗口,即已发送待确认的窗口。

3. Usable Window
可用窗口,即未发送接收方准备好接受的窗口。

4. Left Edge of Send Window
发送窗口的左边界,也就是已发送最后收到确认字节。

5. Right Edge of Send Window
发送窗口的右边界,也就是可以发送的最大字节。

接收窗口

接收的缓冲区比较简单,和发送窗口不一样,接收窗口没有待确认的部分:

1. Receiver Window
接收窗口。

2. Advertised Window
空闲的窗口,等于接收窗口 - 最后收到的字节。

窗口滑动

如上图这种情况,发送端发送了 3、4、5三个Segment,接收端收到了3、5,4丢失了,接收端会回复收到的连续字节最后的位置,也就是回一个ACK3的消息,发送端收到ACK3的消息后,窗口左边缘滑到4的位置,如下图所示:

如果超时还没有收到4的ACK,则进行重传。

SEQ ACK

仅仅依靠滑动窗口并不能解决丢包乱序的问题,还有两个很重要的元素就是序号和确认号。

1. Seq(Sequence number)

序号,跟踪已发送的数据,解决乱序问题。

  1. SYN控制位=1,值为初始序列号 ISN(0 ~ 2^32-1),且段中第一个8位字节从 ISN+1 开始。
  2. SYN控制位!=1,表示段中第一个8位字节的序号。

2. Ack(Acknowledgment number)

确认号,跟踪已接收的数据,解决丢包问题。

  1. ACK控制位=1,表示已经接收的8位字节的序号(不包括当前序号),即希望接受的下一个序列号

我们来看下 rfc793 的描述。

简单理解就是:

  1. Ack = 上一条收到的Seq+length
  2. Seq = 上一条发送Seq+length

针对SEQ序号,有个比较有意思的是:

SYN 的 Segment 里,第一个字节从 ISN+1 开始,
其实可以间接的理解成 SYN Segment 也占一个字节的数据。那么接收方回复的 ACK 就是上一条的 Seq+1。

三次握手示例

我们通过wireshark的一次抓包,来分析一下seqack

  1. C —> S:SYN=1,seq=1296494712,len=0
  2. S —> C:SYN ACK=1,seq=3037568749,ack=1296494713,len=0
  3. C —> S:ACK=1,seq=1296494713,ack=1296494750,len=0
  4. C —> S:PSH ACK=1,seq=1296494713,ack=3037568750,len=106
  5. S —> C:PSH ACK=1,seq=3037568750,ack=1296494819,len=254

参考链接

TCP Sliding Window System

rfc793

Tags: TCP
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章