TCP的可靠性
1.重传2.滑动窗口3.流量控制4.拥塞控制
重传机制
超时重传
场景:1.数据包丢失2.数据应答丢失
超时时间设置:RTO较大:重发慢了阻塞等待,效率低
RTO较小:没有丢失就重传,网络中数据包增多造成阻塞。
RTO是动态的:依据:1.RTT(包往返的时间)平均值2.RTT的范围
快速重传
解决了,超时重传定时器时间过长问题:接收三个相同ACK包后立即重传。
为什么会有相同ACK,当传输中前面一个包丢失,后面包在到达后依旧传丢失之前的传的回应包
但依然不知道该重传那些包,是只重传一个还是所有
SACK
在linux下,通过net.ipv4.tcp_sack打开
原理:在TCP头部添加SACK(缓存了接收到的包)
这样就可以知道该传什么了。
D-SACK
好处:
1.让发送方知道,丢了发生包还是回应的ACK包
2.知道发送方是否网络延迟
3.知道网络是否复制发送方的数据包
滑动窗口
解决频繁阻塞等待应答问题:
窗口大小:
通过接收端告诉发生端,有多少缓存区可以接收数据。发生端根据接收端处理能力来发生数据,避免接受端处理不过来
发送端窗口大小
1.已发送并收到ACK确认数据
2.已发送但未收到ACK确认数据
3.未发生,但在接收方处理范围内
4.未发送,但超出接收发处理范围
发送方指针表示的窗口
1.SND.WND:表示窗口大小
2.SND.UNA:绝对指针,指向已发送但未收到确认的第一字节
3.SND.NXT:绝对指针,指向未发送,但可以发送范围的第一字节
4.指向未发送但超过范围的第一字节(相当指针)
接收端的滑动窗口
1.已接收并确认的数据(等待应用进程读取)
2.未收到,但可以接收的范围
3.未收到,已经超出范围
滑动窗口大小是动态的
当接收方进程读取速度快,在回应发送端窗口大小后,其大小又增大了。
流量控制
TCP提供一种机制,让发送端根据接收端的实际接收能力控制发送的数据量,就是所谓的流量控制。
控制过程
1.客户端发送请求数据报文(求服务端告诉可接收窗口大小)
2.服务端告诉客户端有多少可用,然后分为等待接收数据,和可使用窗口
3.客户端根据服务端发来的可以大小,将数据发给服务端
4.服务端确认收到后,恢复可使用窗口原来大小。
操作系统缓存区与滑动窗口关系
因为不只,窗口分区大小会变化,窗口大小也是会变化的
实际中窗口大小就在操作系统的缓冲区中,缓存区大小固定,缓存的内容越多,窗口的大小越小。就是应用程序没有及时读取缓存内容。
窗口负值
减少缓存的同时有收缩窗口,导致,客户端以为有足够的窗口大小接收,发送的数据超过实际可用空间,数据丢失。
TCP规定:先收缩窗口,在减少缓存,避免丢包
窗口关闭
如果窗口大小问0时,阻止发送方给接收传递数据,直到窗口变为非0为止。
TCP窗口关闭时,潜在的死锁现象
1.互斥2.持有并等待3.环路等待4.不可打断
接收端窗口大小恢复发送给发送端时丢失
发送端等待非0信号,接收端等待接收发送端传来数据
解决死锁现象
接收到零窗口的一方,定时的询问是否恢复。
糊涂窗口
避免为了几个字节的窗口就发送数据
接收端解决小窗口
当窗口大小恢复到小于min(缓存空间的一半),告诉发送端现在窗口为0;
发送端避免发送小数据
1.接收到之前回应包
2.接收到的可发送窗口大小大于一个界限(一半)
拥塞控制
当网络堵塞导致丢包,这时重传导致阻塞更加严重,导致更多的丢包
TCP利用拥塞窗口避免发送方数据在网络中阻塞
什么是拥塞窗口
怎么解决的:发送窗口的值swnd = min(cwnd,rwnd)。
动态变化规则:
1.只要网络中没有出现拥塞阻塞,cwnd就会增大;
2.但网络中出现拥塞,cwnd就减少
一,如何判断出现拥塞:发送超时重传
慢启动
每次增加接收字节的窗口大小
1.一开始窗口为1字节
2.收到ACK后cwnd(窗口)增加收到的字节
拥塞避免算法
当到达启动门限时进入拥塞避免算法
每当收到一个ACK,窗口增加1/cwnd(接收cwnd次后增加一字节)
拥塞发送
发送拥塞时:超时重传
发生重传时,慢启动门限变为窗口大小的一半
窗口大小变为初始值(ss -nli命名查看初始值)
发送快速重传时,网络没有阻塞,只是丢包
窗口大小变为一半。
慢启动门限变为原来窗口大小
快速恢复
发送快速重传时,网络没有阻塞,只是丢包
窗口大小变为一半。
慢启动门限变为原来窗口大小
进入快速算法:
1.拥塞窗口 = 慢启动门限+3
2.重传丢失的数据包
3.再收到重复ACK,将cwnd增加1;
4.将拥塞窗口 = 慢启动门限。
首先,快速恢复是拥塞发生后慢启动的优化,其首要目的是降低窗口大小来减缓拥塞,所以必然出现窗口大小从大到小的改变。
其次,为了尽快将丢失的数据包发送给目标,从根本解决拥塞问题。