4)滑动窗口
1)咱们滑动窗口的效果就是说在我们尽可能地保证可靠性的情况下,尽可能的提高传输效率2)况且咱们进行发送滑动窗口的本质就是说进行批量的发送数据,咱们尽可能说是把等待ACK的时间总体进行缩短,咱们可以把等待一份ACK的时间变成等待多份ACK的时间,速度提升了,等待ACK的时间,甚至少等一些ACK;
1)我们可以看到,由于确认应答机制的存在,这就导致了当前我们每执行一次发送操作,都要等待上一个ACK的到达,只有ACK到了,我们才可以进行发送下一次传输的数据,我们大量的时间都花在等ACK上面了,我们整体等待花的时间多了,那么我们在单位时间内传输的数据量就变少了;
2)ACK:他是确认应答机制里面的,接收者告诉发送者自己受到的那些数据,里面有序列号,发送方要花费很多时间来进行等待,这个过程就消耗了大量的时间,所以我们就要想办法批量去发送,批量去等待;
3)例如A向B发送了1-1000的数据,B返回一个确认序号,A就会进行等待,直到A收到这个确认序号,这个确认序号的意思就是说B告诉A我收到了1-1000B在向A索要1001-2000的数据,如果没有收到ACK,就会进行重传;
1)现在咱们批量发送,一次发一波数据,一次等一波的ACK,这是就把等待多组ACK的等待时间重叠起来了,进一步缩小等待时间提高程序执行效率;
2)窗口大小:一次批量发的数据的长度,称为窗口大小,如果没有批量发送数据的长度限制(完全不等ACK就一通发),其实就没有可靠性而言,窗口越大,整体的效率就会越高,窗口越小整体的效率就会越低
1)当前窗口范围就是1001-4000,也就意味着发送方现在同时发送了1001-2000,2001-3000,3001-4000,我们发送这四组数据的过程中不会等待ACK,这四组都发完了,发送方统一等待4组数据的ACK,我们把一份等待一组ACK的时间,变成了一份等待多组ACK的时间,把等待多组ACK的时间给压缩成一份,TCP是要保证可靠传输的,而保证可靠传输的灵魂就是确认应答,如果说没有这个ACK,可靠传输就形同虚设,等,是必须的,我们只能让他少等一会,如果一次发送的批量数据是N,统一等待一波,此时这里的N就被称为窗口大小
2)滑动的意思是,我们并不需要把N组数据的ACK都等到了,才继续往后发送,而是收到一组ACK,就继续往下发送一组;
2)这时依然在等待四份数据的ACK,并不是在等待四份数据的ACK都到达了,才发新的数据,而是随时收到ACK,就随着向后发送;
此时我们向服务器发送的数据是1-4000的数据,我们进行批量发送,发送之后接收完数据,我们当前的客户端是在进行等待1001,2001,3001,4001四组ACK,咱们的客户端不需要等到4001来了之后才继续向后发送数据,等到一个之后就向后发送一组新的;
3)此时只要1001到了,我们就可以立即向后多发一组(4001-5000),此时等待ACK的范围就是2001,3001,4001,5001,如果是2001这个ACK到了,我们就认为1001-2000之间的数据我们已经收到了,我们也可以继续向后多发1组数据(5001-6000);
4)此时等待ACK的范围就是3001,4001,5001,6001,每一次等到一个ACK,就向后滑动,窗口向后滑动,咱们向后多进行发送一组数据,咱们要等待ACK的范围会发生改变;
变小了改成变多了;
这时传输ACK会存在后发先致的情况?
1)ACK 1001 2001,3001,4001都在网络上运输呢不一定非得是1001先到呀,可能是3001,4001先到呀,这样也没有关系;
2)确认序号表示,从该序号之前,前面的数据已经接收到了,如果收到了4001这个ACK,说明0-1000,1001-2000,2001-3000,3001-4000的数据已经收到了,此时4001前面的这几组ACK收或不收已经不关键了,然后滑动窗口向后滑动三格,然后直接发送4001-5000,5001-6000,6001-7000的数据,7001-8000的数据,
3)当前我们的这个滑动窗口越大,说明就可以认为传输速度越快,窗口大了,同一时间内需要等待的ACK就越多,总体等待ACK的时间就少了;
发送方连续进行发送了0-1000,1001-2000,2001-3000,3001-4000,4001-5000
1)咱们的接收方接收这5类数据之后,发送发就会进行批量等待5组数据的ACK,但是其实发送方们只需要进行等待5001这个确认序号就可以了;
2)当我们的发送方收到5001的时候,也就意味着1-5000的数据我们已经收到了,咱们的1001,2001,3001,4001被进行丢包是毫不影响的,只要我们收到了5001,就已经涵盖了3001和4001所进行表示的信息,我们的窗口就一下子向后面挪了5个格子;
滑动窗口的丢包问题:丢包分成两组情况,我们现在发送0-1000,1001-2000,2001-3000
情况一:数据包已经抵达,ACK却丢了
1)这种情况不打紧,只要不是全丢了就好,发送方如果1001这个ACK丢了,但是3001这个ACK到了,这此时也就知道了(确认序号)3001之前的数据应该都到了(肯定0-1000的数据都已经收到了),此时3000前面的数据已经接收到了 ,这个时候再是否收到1001这个ACK数据包,其实已经没有必要了;
2)实际上有时TCP为了偷懒,滑动窗口下并不是每条数据都有ACK,有时会个几条才会发一个ACK;
1)假设我们的主机A向主机B发送0-1000的数据包,B返回的确认序号就永远是1001这个数据,即使A给B已经向后发送了若干个数据包,此时仍然是在索要1001;
2)索要若干次之后,A就明白了自己丢包了,就会触发超时重传机制,重新发送0-1000的数据包;
情况二:直接发的数据就丢了 ,仍然需要重传(ACK不处理还可以)
因为咱们在这里面的重传只是需要把丢了的那一部分在进行重传了即可,其他已经到了的数据就不需要进行重传了,这样咱们的整体的重传效率就会变得比较高了,这样的重传我们称之为快速重传;
这时1001-2000发的数据包丢了,因为1001丢包了,主机B返回的ACK就会一直索要1001,确认信号就一直是是1001,1001-2000丢了,B就会给A返回一个ACK,由于包丢了,就会一直返回(我收到0-1000的数据,我想要1001之后的数据)
1)A向B发送了1-1000的数据,B返回一个ACK,表示收到了1-1000的数据,还向A索要1001之后的数据;
2)A发送1001-2000的数据,B没反应,不会返回ACK;
3)A在发送2001-3000的数据,B在A不丢包(1001-2000的数据)的情况下会返回一个我已经接收到了2001-3000的数据,确认序号是3001的ACK;
4)但是此时A丢包了,B返回的ACK就变成了我已经收到了0-1000的数据,我还是索要1001-2000的数据,但是实际上2001-3000的数据确实是已经存放到接收方的接收缓冲区里面了;
5)这时A还会发送2001-3000的数据,B确实收到数据了,但返回的ACK确认序号还是1001,6)这时A还会发送3001-4000的数据,但此时B返回的ACK仍然是向A索要1001-2000的数据;(2001-4000的数据已经让B存放在接收缓冲区里面了,但是此时的确认序号仍然是1001,但是0-1000的缓冲区和2001-3000之间还是有空位置的,此时因为1001-2000的数据没到,本属于他的缓冲区是空着的)
6)这时A就知道自己已经丢包了,就会给B再次发送1001-2000的数据,此时B收到了0-4000的数据,就会知道4001之前的数据已经收到了,这时返回的ACK中的确认序号就变成了4001,就是我已经收到了0-4000的数据,就会再次向A索要4001之后的数据了;
我们在这里面的重传只需要把丢了的那一块数据给重传了就可以了,其他已经到了的数据就不需要进行重传了; —————————————————————————————————————————
5)流量控制:保证TCP的可靠性,16位窗口大小,里面就包含了接收缓冲区的剩余大小,
1)他这个机制的本质目的是在控制滑动窗口的大小,她是想要保证可靠性的,窗口的大小决定了传输的效率,窗口越大效率就会越高,单位时间批量等待ACK的时间就会越来越多;
2)窗口越大,资源开销就要更多,窗口越小,效率就得不到保证,发送方发送的贼快,接收方根本处理不过来了,接收方就会把新收到的包给丢了,发送方是不是还得重传;
就是怕咱们的接收缓冲区把数据挤满了,应用程序处理不过来,操作系统内核就把数据包给丢了,数据包一丢,咱们还需要进行重传,没有必要;
3)此时的流量控制就是基于接收方的一个处理数据的能力来限制窗口大小的
TCP这个数据的传输过程类似于生产者,消费者模型;
咱们进行流量控制的关键,就是说衡量接收方的处理速度,咱们在此处就直接使用接收方剩余的接收缓冲区的剩余空间大小来进行衡量当前的处理能力;
1)主机A在给B发送数据,到达了B的接收缓冲区,此时主机A就是生产者,B的应用程序通过SocketAPI来读取数据,被SocketAPI读取的数据,就从缓冲区删掉了,此时应用程序就是消费者,接收缓冲区就相当于消费场所(就相当于是一个阻塞队列,缓冲区里面的数据可以随时被B里面的应用程序通过SocketAPI来进行读取)
2)此时说的窗口大小,就是发送方批量发送的数据有多少,例如主机A发的数据很多,窗口很大,此时接收缓冲区的数据也会增长很快。如果主机B的应用程序读的数据很慢,随着时间的推移,接收缓冲区逐渐满了,如果此时不加任何限制,主机A还是按照原来的速度发,不加任何限制,这时新来的数据没有地方保存了,就被内核丢了;
3)流量控制这件事情,就是根据接收方的处理能力(接收缓冲区的空余于空间大小),来动态决定发送方的发送速率(控制滑动窗口的大小)
1)如果说剩余空间比较大,那么我们就认为B的处理数据的能力就比较强,就可以让A发送的快点
2)如果说剩余的空间比较小,就认为B的处理能力是比较强的,叫可以让A发送的慢一些
1)例如,接收缓冲区的大小现在是4000,当1-1000的数据到达的时候,缓冲区这里用了1000,还剩3000,返回的ACK就会把这个信息发回去,发送方再次发送数据的时候,就会按照3000这个滑动窗口来发送数据;
2)如果窗口大小变成0了(接收缓冲区已经满了),这是发送方就啥也不干了么?
不是的,发送方此时是不会再发送数据了,但是为了可以查询当前接收方的窗口大小,每隔一段时间还会发一个窗口探测包,通过这个包(不会传输具体的业务数据),主要目的是触发ACK,当发送方知道现在就知道当前窗口的大小了,然后再次发送数据
3)为什么TCP传输数据的大小不会受到限制呢?
正常来说,16为窗口大小最大的数字表示65535,那么TCP的窗口大小最大就是65535字节吗?
64K,TCP是传输层协议,在TCP首部40字节选项(在选项中)中包含了一个窗口扩大因子 M,实际上的窗口大小是窗口字段的值左移M位