提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
这篇博客是对上文的补充:主要演示tcp其他的机制
知识点补充部分:
Ack应答和响应是否相同???
ack只是告诉发送方我收到数据了,由操作系统内核负责,会在收到请求之后,立即返回
response响应是携带业务上的数据,由应用程序库决定,取决于代码的实现
举个例子:
当我们用企业微信,或者社交工具抖音发消息时候,对方回复的具体内容是响应,你收到这个消息例如抖音会显示已读是ack
上文讲到:tcp能够保证数据的可靠传输但是却失去了效率,那有什么办法保证可靠性的前提下,尽可能提高传输效率呢!!!
一、滑动窗口机制
提高tcp传输效率的有效机制,先举个例子:
假设我今天要早早做核酸,如果工作人员只开设了一个窗口,那我们要排长长的队,但是如果多设几个窗口,几个大白同时工作,类似于多线程,那么就提高了效率,减少了等待时间
之前主机a大部分时间都消耗在等待ack上,要想提升效率,就是不等ack,直接发下一条数据,但却不是完全不等,批量处理一波消息,等一波Ack,再发一条消息,这样就不需要等待,就可以直接发送数据的量,称为窗口大小
对比使用滑动窗口前后效果:
使用后:
注意:主机A是收到一个ACK,就继续发下一条数据,而不是等所有的ACK都到了,才统一发下一组
为了更好的理解窗口为何是滑动,画了简图:
主机a批量发送一些数据(1001-5000),当没有收到2001的ack应答时:
当收到ack时,2001到达主机a主机a立刻给主机发送5001-6000的数据
此时a等待ack的范围就是2001-6000了
白色框表示等待确认的数据,在2001到达之前a等待的数据是1001-5000,到达后把1001-2000这个记录从白色框删掉,同时发送5001-6000数据,继续等待5001-6000ack,等待的数据仍然是4条,看起来长度没变,只是整体向右移了一下
问题:
那滑动窗口机制这么好用,为何不把窗口设置成无限大????这样不就不等待ack了??
且听如下分析先了解
快速重传
刚才我们举的例子是正常情况,如果出现丢包/乱序怎样?
丢包为例:
1.数据报已经到达,ack丢了
假设我们丢包率有50%,主机b收到前1000的数据,但是1001的ack丢了,当主机a继续发送1001-2000的数据时,主机b就会直接返回2001的ack已经包含了前1000的数据,并不会影响通信
比如我拿到大学毕业证,那么高中毕业证初中毕业证就不重要了(已经确认了我是大学生的身份,那我一定之前是高中/初中生)
2.传的数据报丢了:
在上述设定中,只是把丢的数据报进行了重传,没丢的包,没有重传(没有做任何拖泥带水的工作)上述的重传过程,效率也是很高的 这就是快速重传(搭配滑动窗口的超时重传)
注意快速重传固然好,不是说超时重传没用了,当数据很少时,按照超时重传,需要批量传输就快速重传,
解答上述问题:
如果窗口过大,发送的速度是快了,但是接受方不一定会收到数据
接受方处理速度跟不上,就会导致接受方丢失一部分数据,tep为了实现可靠性又得重新传数据,这就让本来就不富裕的地方,又学上加爽
比如俩天卷完java固然快,但是真的能学会嘛??,如果我们知识没有及时巩固没学会(丢包),岂不是再需要花时间研究(重传),这就需要一定的开销
那这个学习的度(发送速率)应该如何控制呢,接着道来!
5.流量控制机制
在滑动窗口的基础之上,对发送速率做出的限制,就是限制发送方的窗口不要太大
接受方对于发送方的反制,接受方根据自己的接受能力,来反向影响发送方接下来的发送速率
接受方的接受速率如何量化
接受方使用接受缓冲区的剩余大小,来作为发送方发送的速率(窗口大小)参考数值
类似于一个池子,进水和放水操作,传输数据就是进水,返回ack就是放水,通过水池线来判断当前放水的速率(接受方的处理能力)
然后当接受方b收到a的数据之后,就会给a一个反馈,把接收区缓存空间剩余空间大小的值(水位)反馈给发送方:通过16位窗口大小借助选项
那么第一次进水时,多少水合适呢?
如何确定确定窗口大小
当水位线变成0时(水满了),发送端再发水就会丢失(丢包),这个时候a不给b发送数据,,b就没办法返回ACK,当水有余位时候,如何告知发送端继续发水呢?窗口探测,不携带社和业务数据,只是一个Bit来向接收方询问窗口大小,接受方返回一个更新的值(周期性发送)
6.拥塞控制机制
也是通过接收方的处理能力,来衡量发送方的速率的
实际的网络环境非常复杂,中间这些设备交换机,路由器是很难衡量是否会丢包
解决思路:
流量控制是控制发送方的窗口大小,拥塞控制也是在控制发送方的窗口大小的
具体实现:
1.开始的时候指数增长,达到阈值,线性增长