TCP重传,滑动窗口,流量控制,拥塞控制
TCP重传机制:
- 超时重传
- 快速重传
- SACK
- D-SACK
通过序列号与确认应答判断是否要重传
超时重传:
超过指定时间没有收到确认应答报文,就会重发该数据
触发超时重传的情况:
- 数据包丢失
- 确认应答丢失
RTT:数据发送时刻到接受到确认的时刻的差值 包的往返时间
RTO:超时重传时间
RTO太长或太短:
- 太长,效率差,重发慢,丢了半天才重发,性能差
- 太短:没有丢就重发,增加网络拥塞,导致更多的超时
超时重传时间RTO的值应该略大于报文往返RTT的值
如果超时重发的数据,再次超时的时候,又需要重传,TCP的策略是超时间隔加倍
也就是每次遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁发送
超时重传缺点:
超时周期长,用快速重传机制来解决
快速重传
不以时间为驱动,而是以数据驱动重传
当收到三个相同的ACK报文,会在定时器过期之前,重传丢失的报文段
缺点:不知道重传一个,还是重传所有的问题
于是有了SACK方法:选择性确认
在TCP头部加一个SACK,可以将已收到的数据的信息发送给发送方
这样就可以知道哪些数据接收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据了
相当于是快速重传知道了该重传一个还是全部
D-SACK
使用SACK来告诉发送方有哪些数据被重复接受了
D-SACK的作用:
- 可以让发送发知道,是发出去的包丢了,还是接收方回应的ACK包丢了
- 可以知道是不是发送方的数据包被网络延迟了
- 可以知道网络中是不是把发送发的数据包给复制了
滑动窗口:
上面的传输方式有一个缺点:数据往返时间越长,通信的效率就越低
窗口就是指无需等待确认应答,而可以继续发送数据的最大值
窗口实质上是一个缓存空间,发送发主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据,如果收到确认应答,此时数据就可以从缓存区清除
确认应答报文丢也没事,可以累计确认,累计应答
窗口大小:
通常是由接收方的窗口大小来决定的
否则接收方可能无法正常接收到数据
发送方的滑动窗口:
有四部分:
- 1 是已发送并收到ACK确认的数据
- 2是已发送但未收到ACK确认的数据
- 3 是未发送但总大小在接受方处理范围内
- 4是未发送但总大小超过接收方处理范围
当发送方把数据全部都发送出去,可用窗口3 为0 在未接到ACK之前无法发送数据
接收方的滑动窗口
三部分:
- 已经成功接受并确认的数据(等待应用进程读取)
- 未收到数据但可以接收的数据
- 未收到数据并不可以接受的数据
接收窗口和发送窗口的大小是相等的吗?
并不完全相等,接受窗口的大小约等于发送窗口的大小的
流量控制:
TCP提供一种机制可以让发送方根据接收方的实际接受能力控制发送的数据量,这就是所谓的流量控制
先发一部分比如80,再发一部分比如120,然后发送方的可用窗口为0了,然后等待80的确认报文,
操作系统缓冲区和滑动窗口的关系:
发送窗口和接受窗口中所存放的字节数,都是放在操作系统内存缓冲区中的,而操作系统的缓冲区,会被操作系统调整
为了避免丢包:TCP规定是不允许同时减少缓存又收缩窗口的,而是采用先收缩窗口,过段时间再减少缓存
当应用程序没有及时读取缓存时,发送窗口和接收窗口
根据流量控制,发送方随着接收方的窗口逐渐减小,直到最后两个窗口减小为0 窗口关闭
数据丢包的发生是因为:当服务器资源紧张的时候,操作系统直接减少了接收缓冲区的大小,这是应用程序无法及时读取缓存数据
TCP是通过让接收方指明 希望从发送方接受的数据大小(窗口的大小)来进行流量控制
如果窗口大小为0时,就会阻止发送方给接收方传递数据,知道窗口变成非0这就是窗口关闭
但是这里存在一个问题:如果接收方向发送方发送的窗口非0的ACK报文,丢失,那么会造成死锁
TCP如何解决窗口关闭时,潜在的死锁现象
TCP,为每一个连接设有一个持续定时器:只要TCP链接一方收到对方的零窗口通知,就启动计时器
这样即使是非0ACK丢失,计时器超时之后依然会发送窗口探测报文,相当于是双保险
糊涂窗口综合症:
如果接收方腾出几个字节并告诉发送方现在有几个字节的窗口,而发送方会义无反顾的发送这几个字节
相当于开公交车送1个人,造成资源的浪费
解决办法:接收方满足不通知小窗口给发送方,发送方开启Nagle算法(延时处理)
拥塞控制
避免「发送方」的数据填满整个网络。
拥塞窗口:发送方维持的一个状态,根据网络拥塞个程度动态变化的
变化规则:
- 只要网络中没有出现拥塞,cwnd就会增大
- 但是如果出现拥塞,cwnd就会减少
如何判断是否出现拥塞 :
只要发送了超时重传就认为出现了拥塞
拥塞控制的四个算法
- 慢启动
- 拥塞避免
- 拥塞发生
- 快速恢复
慢启动:一点一点提高发送的数据包
当发送方每收到一个ACK,拥塞窗口大小+1
20 21 22 23 24
1 2 4 8 16
当拥塞窗口的大小大于慢启动门限的时候使用拥塞避免算法
拥塞避免算法:
每当收到一个 ACK 时,cwnd 增加 1/cwnd
8 9 10 11 12
拥塞避免算法将指数增长变成线性增长
然后慢慢增长之后会出现拥塞,出现丢包,超时重传了
就进入了拥塞发生算法
当发生了「超时重传」,则就会使用拥塞发生算法。
直接开始慢启动,一夜回到解放前,并且更新慢启动门限
发生快速重传的拥塞发生算法:
拥塞窗口大小变为原来一半
进入快速恢复算法
还会维持在比较高的值,后续呈线性增长