前言:计算机网络方面看了谢希仁的《计算机网络》和《TCP/IP详解卷一》看完后似懂非懂,直到有一天买了林沛满写的《WireShark网络分析就这么简单》和《WireShark网络分析的艺术》才算真正能把所有的知识点串联起来,写的非常好,非常容易看懂,而且你会发现这两本书很快就看完了。下面是根据我的理解的一个整理:

知识点:RTO,MTU,MSS,发送窗口,接受窗口,慢启动,拥塞避免,超时重传,快速重传,快恢复

提升发送效率:延迟确认,Nagle,SACK

前言:

MTU(Maximum Transmission Unit):最大传输单元,由硬件规定,如以太网的MTU为1500字节。
MSS(Maximum Segment Size):最大报文长度,MTU=MSS + 20byte(TCP头) + 20byte(IP头)
RTO(Retransmission TimeOut ):超时时间,发出一个报文后,等待RTO时间还未收到其确认报文,则表示超时,进行超时重传。
延迟确认:表示当收到一个报文后,不立即发送一个确认报文,而是等待,一般等到200ms,如果没有数据发送给对方,就把这个确认报文发不出,如果有数据发送给对方时,将这个确认报文一起以一个包的形式发给对方。
Nagle:表示当前一个发送的数据报没有收到ACK前,又来了一个要发送的数据,且其大小小于1个MSS时,发送方不直接发送,而是等待更多要发送的数据直到达到1个MSS。
SACK:由于触发超时重传和快速重传后,并不知道丢失的包后面的哪些数据收到,哪些没有收到,于是还需要继续通信或重发后面的包,所以为了提高发送效率,采用SACK,可以知道哪些包丢失,哪些没有丢失。

1. 滑动窗口

滑动窗口:发送方维护一个发送窗口,接收方维护一个接收窗口,发送方通过ACK报文中的16位窗口大小字段控制发送窗口的滑动;
接收方通过接收到的数据和缓冲区的大小控制接收窗口的滑动,通过16位窗口大小字段可以控制发送方发送速率,通过ack+seq可以知道接收窗口中哪些数据没收到(丢失)。
简言之:发送窗口接收窗口在数据通信过程中是滑动状态的,故形象理解为滑动窗口。

2. 流量控制

流量控制是通过接收和发送双方维持一个窗口以控制发送方发送速率,保证接收方来得及接收。接收方回复的确认报文中的窗口字段(16位窗口大小)可以用来控制发送方窗口大小,从而影响发送方的发送速率。

流量控制与拥塞控制的区别

  • 流量控制往往是指在发送端和接收端之间的点对点通信量的控制. 流量控制所要做的是抑制发送端发送数据的速率, 以便使接收端来得及接收;
  • 而拥塞控制必须确保通信子网能够传送待传送的数据, 是一个全局性的问题, 涉及网络中所有的主机、路由器以及导致网络传输能力下降的所有因素.

3. 拥塞控制

TCP 主要通过四种算法来进行拥塞控制慢开始拥塞避免快重传快恢复。发送方需要维护有一个叫做拥塞窗口(cwnd)的状态变量。
注:拥塞窗口发送方窗口的区别,拥塞窗口只是一个状态变量,实际决定发送方能发送多少数据的是发送方窗口。

为了便于讨论,做如下假设:

  1. 接收方有足够大的接收缓存,因此不会发生流量控制;
  2. 虽然 TCP 的窗口基于字节,但是这里设窗口的大小单位为报文段。

图解释:
2 超时:表示丢包触发超时重传
4 3-ACK:表示收到3个相同确认报文,触发快速重传

慢开始与拥塞避免

三次握手后发送方会知道接收方的窗口大小,设10MSS,但是此时不会立即一次性向网络中推10MSS包,而是执行慢开始。
最初执行慢开始时,令 cwnd=1,发送方只能发送 1 个报文段;当收到确认后,将 cwnd 指数加倍,因此之后发送方能够发送的报文段为:2、4、8 ...

注意到慢开始每个轮次都将 cwnd 加倍,这样会让 cwnd 增长速度非常快,从而使得发送方发送的速度增长速度过快,网络拥塞的可能也就更高。设置一个慢开始门限 ssthresh,当 cwnd >= ssthresh 时,进入拥塞避免阶段,每个轮次只将 cwnd 加 1。

如果出现了超时重传,则令 ssthresh = cwnd / 2,然后重新执行慢开始

TIP:慢开始门限ssthresh的初始值设置是根据网络情况RTT等确定,上图是假设 ssthresh = 1616个MSS

cwnd<ssthresh,慢开始算法
cwnd>ssthresh,停止使用慢开始算法,改用拥塞避免算法。
cwnd=ssthresh,既可以慢开始也可以拥塞避免算法。

快重传与快恢复

在接收方,要求每次接收到报文段都应该发送对已收到有序报文段的确认,例如已经接收到 M1 和 M2,此时收到 M4,应当发送对 M2 的确认。

在发送方,如果收到三个重复确认,那么可以确认下一个报文段丢失,例如收到三个 M2 ,则 M3 丢失。此时执行快重传,立即重传下一个报文段。

在这种情况下,只是丢失个别报文段,而不是网络拥塞,因此执行快恢复,令 ssthresh = cwnd / 2cwnd = ssthresh,注意到此时直接进入拥塞避免

TIP:关于触发超时重传快重传ssthresh值的设置有很多算法,有的认为ssthresh应该为,当前窗口的一半,有的认为应该为,当前已收到报文窗口的一半。算法很多,不深入了。

4. TCP如何保证可靠性

  • 序号: TCP连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号;
  • 确认: TCP首部的确认号是期望收到对方的下一个报文段数据的第一个字节的序号。当数据发送出去之后, 发送方缓存区会继续存储那些已经发送但未收到确认的报文段,以便在需要的时候重传。TCP默认使用累计确认,即TCP只确认数据流中至第一个丢失字节为止的字节。
  • 重传: 有两种事件会导致TCP对报文段进行重传:超时重传超时和快速重传。
    1. 超时重传: TCP每发送一个报文段,就对这个报文段设置一次计时器。只要计时器设置的重传时间到期但还没有收到确认,就要重传这一报文段。
    2. 快速重传: 重复确认某个报文段的ACK,而发送方先前已经收到过该报文段的确认; TCP规定当发送方收到对同一个报文段的3个冗余ACK时,就可以认为跟在这个被确认报文段之后的报文段已经丢失;
  • 校验: TCP将保持它首部和数据的校验和。这是一个端到端的校验和,目的是检测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP将丢弃这个报文段并且不确认(导致对方超时重传);
  • 重排: TCP承载于IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。TCP将对收到的数据进行重新排序。IP数据报会发生重复,TCP的接收端会丢弃重复的数据。
  • 流量控制: TCP还能提供流量控制。TCP连接的每一方都有一定大小的缓冲空间。
  • 分片: 应用数据被分割成TCP认为最适合发送的数据块,称为TCP报文段传递给IP层。