TCP可靠性保证总结

​相信大家都知道 TCP 是一个可靠传输的协议,那它是如何保证可靠的呢?总的来说,有下面几点

  1. 序列号和确认应答信号
  2. 连接管理
  3. 重传机制
  4. 滑动窗口控制
  5. 流量控制
  6. 拥塞控制

一、序列号和确认应答信号

在TCP连接中,发出的数据都带有一个序列号,而接收端收到数据的同时,发送给发送端的数据中会有带有相应序列号+1的确认应答信号,这样一来,如果发送方没有收到确认应答信号,就知道发生了数据包丢失的情况。

数据报求实其实也分两种情况:
第一种:数据发送过去的途中丢失,这个时候接收端没有收到数据包,也就无法发出确认应答信号,在一定时间过后,发送端没有接收到确认应答信号,那么就会重新发送一次数据。

第二种是接收端接收到了数据,但是发送的确认应答信号丢失了,这种情况下发送端在一定时间后也会进行数据重发,但是接收端因为之前已经接收到了这个数据,所以再次接收的时候会放弃这个数据,然后发送一个确认应答信号给发送端。

二、连接管理

这个就是常见的三次握手和四次挥手了,可以看这篇文章:最通俗易懂的TCP三次握手四次挥手详解_tcp三次挥手四次挥手-CSDN博客

三、重传机制

TCP实现可靠传输的方式之一,是通过序列号与确认应答

在TCP当中,当发送端的数据达到接受主机时,接收端主机会接受一个确认应答,表示已收到消息
在这里插入图片描述

TCP针对数据包丢失的情况,会用重传机制解决:

  • 超时重传
  • 快速重传
  • SACK
  • D-SACK

1.超时重传

重传机制的其中一个方式,就是在发送数据的时候,设定一个定时器,当超过指定的时间后,没有收到对方的ACK确认应答报文,就会重发该数据,也就是我们常说的超时重传
请添加图片描述

TCP会在以下两种情况发生超时重传:

  • 数据包丢失
  • 确认应答丢失 超时时间应该设置为多少呢? RTT(Round-Trip Time
    往返时延):就是数据从网络一端传送到另一端所需的时间,

也就是包的往返时间
请添加图片描述

超时重传时间是以RTO(Retransmission Timeout 超时重传时间)表示。

超时重传时间RTO的值应该略大于报文往返RTT的值。
在这里插入图片描述

实际上【报文往返RTT的值】是经常变化的,因为我们的网络也是时常变化的。也就是因为【报文往返RTT的值】是经常波动的,所以【超时重传时间RTO的值】应该是一个动态变化的值。

估计往返时间,通常需要采样以下两个:

  • 需要TCP通过采样RTT的时间,然后加权平均,算出一个平滑RTT的值,而且这个值还要不断的变化,因为网络状况在不断地变化
  • 除了采样RTT,还要采样RTT的波动范围,这样就避免了RTT如果有一个大的波动的话,很难被发现的情况

2.快速重传

TCP还有l另外一种快速重传(Fast Retransmission)机制,它不以时间为驱动,而是以数据为驱动重传。

快速重传的工作方式是应当收到三个相同的ACK报文时,会在定时器过期之前,重传丢失的报文段。
在这里插入图片描述

快速重传机制只解决了一个问题,就是超时时间的问题,但是它依然面临着另外一个问题。就是重传的时候,是重传之前的一个,还是重传所有的报文段的问题。

根据TCP的不同实现,以上两种情况都有可能实现。为了解决不知道该重传哪些TCP报文,于是就有了SACK方法。

3.SACK

还有一种实现重传的机制j叫:SACK(Selective Acknowledgement选择性确认)。

这种方式需要在TCP头部【选项】字段里加一个SACK的东西。它可以将缓存的地图发送给发送方,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。
在这里插入图片描述

4.D-SACK

Duplicate SACK,其主要使用了SACK来告诉【发送方】哪些数据被重复接受了

四、滑动窗口

1.滑动窗口的概念

TCP每发送一个数据,都需要进行一次应答。当收到了上一个应答,在发下一个数据,但这种方式效率比较低。数据包往返时间越长,通信的效率就越低

为了解决这个问题,TCP引入了窗口概念。即在接收窗口范围内的数据,无需等待确认,可以继续发送窗口内数据,直到把发送窗口数据传输完毕

窗口的实现实际上是在操作系统开辟一个缓存空间(空间和序号都是有限的,并且要循环使用,一般为环形队列),发送主机在等到确认应答返回之前,必须在缓冲区保留已发送窗口的数据(超时重传)。收到应答后,将此数据清除。

2.滑动窗口的使用

  • TCP的滑动窗口是以字节为单位的。
  • TCP通信是全双工通信,通信中的每一方都在发送和接收报文段。每一方都有自己的发送窗口和接收窗口。

发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。
我们先来看看发送方的窗口,下图就是发送方缓存的数据,根据处理的情况分成四个部分,其中深蓝色方框是发送窗口,紫色方框是可用窗口:
请添加图片描述

  • 1 是已发送并收到 ACK确认的数据:1~31 字节
  • 2 是已发送但未收到 ACK确认的数据:32~45 字节
  • 3 是未发送但总大小在接收方处理范围内(接收方还有空间):46~51字节
    4 是未发送但总大小超过接收方处理范围(接收方没有空间):52字节以后

在下图,当发送方把数据「全部」都一下发送出去后,可用窗口的大小就为 0 了,表明可用窗口耗尽,在没收到 ACK 确认之前是无法继续发送数据了。
请添加图片描述
接下来我们看看接收方的窗口,接收窗口相对简单一些,根据处理的情况划分成三个部分:

  • #1 + #2 是已成功接收并确认的数据(等待应用进程读取);
  • #3 是未收到数据但可以接收的数据;
  • #4 未收到数据并不可以接收的数据;

请添加图片描述
其中三个接收部分,使用两个指针进行划分:

  • RCV.WND:表示接收窗口的大小,它会通告给发送方。
  • RCV.NXT:是一个指针,它指向期望从发送方发送来的下一个数据字节的序列号,也就是 #3 的第一个字节。
  • 指向 #4 的第一个字节是个相对指针,它需要 RCV.NXT 指针加上 RCV.WND 大小的偏移量,就可以指向 #4 的第一个字节了。

接收窗口和发送窗口的大小是相等的吗?

并不是完全相等,接收窗口的大小是约等于发送窗口的大小的。

因为滑动窗口并不是一成不变的。比如,当接收方的应用进程读取数据的速度非常快的话,这样的话接收窗口可以很快的就空缺出来。那么新的接收窗口大小,是通过 TCP 报文中的 Windows 字段来告诉发送方。那么这个传输过程是存在时延的,所以接收窗口和发送窗口是约等于的关系。

五、流量控制

发送方不能无脑的发送数据给接收方,要考虑接收方数据处理能力.

如果无脑发送数据的速率超过了接收方处理的速率,会触发发送方的重发机制导致资源的浪费.为此引入了流量控制的机制:发送方会根据接收方的实际接受能力控制发送的数据量

流量控制的具体流程:

  1. 接收端会将自己的接收缓冲区的大小放入TCP首部的"窗口"字段,通过ACK反馈给发送端. 这个"窗口"也就是TCP首部的"16位窗口大小",当然这个缓冲区的大小不止65535位.在TCP首部40字节选项中还包含了一个窗口扩大因子M,实际缓冲区大小是窗口字段的值左移M位.
  2. 当接收端发现自己的缓冲区中的数据快满了,就会减小窗口的值然后反馈给发送端,发送端依据此放慢自己的发送速度
  3. 当接收端发现自己的缓冲区已经满了,就会将窗口的值设置为0,发送端根据这个值变为0后将不再发送数据,但会定期的发送一个窗口探测的数据段用来得到接收区中缓冲区的剩余大小.当接收端中缓冲区大小有剩余时,会向发送端发送一个窗口更新通知.

1.操作系统缓冲区与滑动窗口的关系

发送方和接收方的滑动窗口中存放的字节数实际上都是放在操作系统内存缓冲区的.

当应用进程没办法即使读取缓冲区中的内容时,会对缓冲区造成影响,进而会对窗口造成影响.

当服务器资源十分紧张时会缩小接收缓冲区的大小.因此当客户端发送数据包给服务器时,服务器由于资源紧张减少接收缓冲区的大小,并且应用层无法读取数据,进一步减少了接收窗口的可用大小.也就是说此刻发送窗口的大小是大于接收窗口的(因为接收窗口因为资源紧张减少了大小),在接收方返回最新窗口之前,假设发送了一个超过此时接收方窗口大小的数据,则会造成服务器丢包,同时客户端中的发送窗口的大小会变成负值.

因此,为了防止这种情况发生,TCP规定不允许同时减少缓存且收缩窗口.而是先收缩窗口,之后再减少缓存,避免丢包现象的发生.

2.窗口关闭

当接收方的窗口大小变为0时,意味着窗口关闭,告诉发送方在这一段时间内不要再发送数据.当接收方数据处理了一部分以后,会主动发送一个ACK报文给发送方告知发送方可以发送数据了

这里存在一个危险:当接收端窗口大小从0变为非0后,传递给发送方的ACK报文如果发生丢包,发送方和接收方就会处于一种死等的状态

请添加图片描述
为了解决接收窗口为0后发送的ACK报文的丢包造成的死锁问题,TCP为每一个连接设定一个持续定时器,这个持续定时器从发送方接收到接收方发送的窗口大小为0的通知开始计时.当计时器超时,发送方就会发送一个窗口探测报文,而对方在收到窗口探测报文后会给出自己当前窗口的大小:如果为0,则重启定时器;如果不为0,则打破死锁.窗口探测报文在连续探测3次后收到的窗口大小认为0,TCP一般就会发送RST报文来中断连接

3.糊涂窗口综合症

如果接收方太忙了,来不及取走接收窗口里的数据,那么发送方的发送窗口会越来越小.到最后,窗口中只剩下很小的可用区域,然后每次还得发送接收窗口的大小给发送方,然后发送方还会顽固地发送很少字节数的数据,这就是糊涂窗口综合症.

用TCP+IP头部一共40个字节的报文去发送数据只有几个字节的数据会耗费太多不必要的资源

要解决糊涂窗口综合症,就需要避免接收方将小窗口发送给发送方以及避免发送方发送小的数据给接收方.

  • 避免接收方放松小窗口给发送方

接收方发送窗口的策略:当窗口大小小于min(MSS,缓存空间/2)时,会通告一个窗口大小为0的数据报文给发送方.当接收方的可用窗口大小大于min(MSS,缓存空间/2)后把窗口的真实大小返回给发送方.

  • 避免发送方发送小的数据给接收方

发送方发送的策略:使用Nagle算法延时处理,当不满足下述任意一个条件时则不发送数据

  1. 要等到窗口大小>=MSS或发送数据大小>=MSS
  2. 收到之前发送数据的ack包

由此可知Nagle算法是依靠避免接收方发送小窗口给发送方

所以避免糊涂窗口综合症的方案是:不通告小窗口给对方+Nagle算法

Nagle算法默认是打开的,但对于某些特殊的场景需要发送小数据给对方时,则需要手动关闭Nagle算法(设置TCP_NODELAY)

六、拥塞控制

流量控制可以保证发送方发送的数据填满接收方的缓存,但并不能对网络拥堵等情况作出相应的反应.当网络拥堵时,发送的数据包丢包,时延的概率就更大.因此发送方就会重传数据,重传的数据会加剧网络拥堵,然后会更容易丢包,时延.因此会造成一种恶性循环. 因此引出了拥塞控制:当网络发生拥堵时要减少发送的数据量

为了在发送方动态调节要发送的数据量,需要依靠一个拥塞窗口.

拥塞窗口是发送方维护的一个状态量,根据网络拥塞程度动态变化.因此滑动窗口的大小就等于min(拥塞窗口,接收窗口)

当网络中没有拥塞时,拥塞窗口会增大;当网络中出现拥塞时,拥塞窗口会减小.网络是否拥塞通过发送方是否能在规定时间内接收到ACK报文来衡量.

拥塞控制由4个算法构成

1.慢启动
2.拥塞避免算法
3.拥塞发生
4.快速恢复

1.慢启动

TCP在刚建立连接完成后,会有一个慢启动的过程.这个慢启动就是一点一点增加发送包的数量.

慢启动的规则:当发送方每接收到1个ACK,拥塞窗口的大小就会+1.(这个1指的是1个MSS大小的数据包)
请添加图片描述

因此,拥塞窗口的大小随着接收ACK数量的增多,1,2,4,8…呈指数趋势增长.慢启动过程有一个慢启动门限ssthresh,当拥塞窗口大小小于ssthresh时,采用慢启动算法,当拥塞窗口大小大于等于ssthresh时,采用拥塞避免算法.一般来说ssthresh的大小为66535字节.

2.拥塞避免算法

当拥塞窗口大小大于等于ssthresh时,会采用拥塞避免算法.

拥塞避免算法的规则:当发送方没接收到1个ACK,拥塞窗口的大小就会增加(1/拥塞窗口大小)

我们从慢启动的指数增长中退出到拥塞避免中,在拥塞避免中,拥塞窗口的大小会呈线性增长.

之后当拥塞窗口的大小增长到一定程度后,也会发生网络堵塞.此时就会触发发送方的重传机制,因此也就进入了拥塞发生
请添加图片描述

3.拥塞发生

当拥塞窗口的大小增长到发生网络堵塞触发发送方的重传机制时采用拥塞发生算法.

拥塞发生算法的使用取决于采用哪种重传机制

  1. 超时重传

使用拥塞发生算法:ssthresh的值变为拥塞窗口大小的一般,拥塞窗口的大小变为拥塞窗口的初始值.之后就继续慢启动.

这种拥塞发生算法过于激进,相当于一个断崖式下降,会造成网络卡顿

  1. 快速重传

当触发快速重传机制时,TCP会认为这种情况丢包现象不严重,因此拥塞窗口变为原来的一半,ssthresh变为新的拥塞窗口大小,之后进入快速恢复算法.

4.快速恢复

快速恢复是在快速重传的前提下才发生的.快速恢复算法认为既然能够触发快速重传接收到3个重复的ACK包,说明网络拥塞情况不严重,不需要向超时重传的拥塞发生算法那么激烈.

快速恢复算法的流程

  1. 拥塞窗口大小加3(3指的是快速重传中接收到的3个相同的ACK包)
  2. 重传丢失的数据包.
  3. 如果收到重复的ACK包拥塞窗口的大小+1(这个过程是尽可能重传丢失的数据包)
  4. 当收到新的ACK包时,说明之前丢失的包已经全部发送完.至此快速恢复算法结束.拥塞窗口大小变为ssthresh的值,然后进入拥塞避免算法.

快速恢复算法相当于是对慢启动算法的优化.进入快速优化算法说明当前拥塞窗口的大小较大,会引发网络拥堵,所以要减小拥塞窗口的大小,但网络拥堵情况又没有太严重所以不需要像超时重传的拥塞发生算法那样下降的那么剧烈.

请添加图片描述
上图是触发超时重传的拥塞控制过程

下图是触发快速重传的拥塞控制过程

请添加图片描述

  • 31
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值