欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 【TCP协议】流量控制 滑动窗口

【TCP协议】流量控制 滑动窗口

2025/2/2 4:46:41 来源:https://blog.csdn.net/2301_76973016/article/details/145406824  浏览:    关键词:【TCP协议】流量控制 滑动窗口

目录

说明:

流量控制

为什么要流量控制

什么是流量控制

如何控制流量:16位窗口大小

如果主机 B 一直没空间呢?标志位 PSH

滑动窗口:全面认识序号和确认序号

为什么需要滑动窗口?

理解滑动窗口

序号和确认序号

窗口如何向右滑动

最左侧的报文丢包了:

快重传

最左侧报文没丢,但中间或者最右侧的报文丢包了:

应答丢包了:

按序处理


说明:

在本文中,主机 A 表示通信的发送方,主机 B 表示通信的接收方。

流量控制

为什么要流量控制

TCP 支持全双工,是因为发送方和接收方都有发送缓冲区和接收缓冲区。双方在通信时,

1、如果发送方发送消息太快了,就会导致接收方的接收缓冲区满了,接收方来不及接收新来的报文,导致新来的报文被丢弃,发送方没有收到对应的报文的应答,就会超时重传,一直超时重传,就会浪费网络资源;

2、如果发送方发送消息太慢了,就会影响通信的效率。

不难看出,需要进行流量控制,帮助维持网络的稳定性和效率。

什么是流量控制

流量控制是一种用于管理数据在网络中传输速率的机制,旨在防止数据发送方以超过接收方处理能力的速度发送数据,从而避免造成数据丢失、网络拥塞以及其他潜在问题。它确保了通信双方能够高效且可靠地交换数据。

如何控制流量:16位窗口大小

进行流量控制,就需要让发送方(主机A)知道接收方(主机B)的接受能力,而接受能力就是接收方(主机B)的接收缓冲区的剩余空间的大小,所以主机B就在报文中的16位窗口中填上自己接收缓冲区的大小,通过 ACK 报文告诉主机 A。

窗口大小字段越大, 说明网络的吞吐量越高;主机 B 一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给主机 A ;主机 A 接受到这个窗口之后, 就会减慢自己的发送速度;

如果主机 B 缓冲区满了, 就会将窗口置为 0;这时主机 A 不再发送数据,但是需要定期发送一个窗口探测数据段, 使主机 B 把窗口大小告诉主机 A ,主机 B 也会向主机 A 主动发送窗口更新通知,这两种策略会同时生效,保证尽快恢复通信。

如果主机 B 一直没空间呢?标志位 PSH

ssize_t read(int fd, void *buf, size_t count);

在 read 函数中,可以通过 count 参数指定想要读取的字节数,但 read 实际返回的字节数可能会少于请求的数量。例如,到达文件末尾时,或者当读取过程中出现错误时,read 将返回一个不大于 count 的值,包括可能返回 0(表示文件结束)或 -1(表示发生错误)。

可以看出主机 B 上层在读取接收缓冲区的字节时,会尽量按照我们设置的字节数来读取。如果主机 B 的接收缓冲区一直没有空间,说明上层一直没有读数据的速度太慢了,能读数据时却没有尽快读走数据,主机 A 可以发送标志位 psh 置为 1 的报文,催主机 B 的上层尽快读取数据,尽快腾出空间,不要等到列车满员了再发车,现在就可以发车了。

当发送方设置PSH标志时,意味着它希望接收方尽快将已接收到的数据递交给上层应用,而不是等待更多数据的到来以形成更大的报文段。
 

滑动窗口:全面认识序号和确认序号

为什么需要滑动窗口?

 如果发送方一次发送一条报文,接收方发送 ACK 报文,发送方收到 ACK 报文后再继续发送报文,这样一发一收的效率很低。所以发送方一次性发送多条数据,就可以提高效率。

一次性发送多条报文,就需要对发送缓冲区的字节进行管理,哪些字节组成的报文是已经发送且已经收到应答的,哪些字节组成的报文是已经发送但未收到应答,哪些字节组成的报文是还没有发送的。

如果把发送缓冲区看成一个数组,那么每个字节都有自己的序号,对不同类型的报文的管理,就可以看成对发送缓冲区的字节的管理。

理解滑动窗口

有了上面的认识之后,就需要有一个窗口对发送缓冲区的字节进行分类,窗口内的字节组成的报文就是已经发送但未收到应答的,窗口左侧的字节组成的报文就是已经发送且已经收到应答的,窗口右侧的字节组成的报文就是未发送的。

 有了窗口后,我们规定窗口只能向右滑动,不能向左滑动,如果向左滑动,那么已经发送且已经收到应答的报文就变成已经发送但未收到应答的报文,打乱了规则。那么窗口如何向右滑动呢?

序号和确认序号

在了解窗口如何向右滑动时,我们需要重新理解一下 TCP 报文中序号和确认序号的意义。

序号:表示该报文段中的第一个数据字节的编号。

确认序号:如果接收方接收到了报文,那么 ACK 报文中的确认序号就是 已经接收到的字节的编号+1。即,接收方已经收到了确认序号之前的字节!

    窗口如何向右滑动

    了解了序号和确认序号后,我们就可以知道,如果窗口内最左侧的报文收到了应答,那么窗口才可以向右滑动,但了解到这里还不能完全理解窗口的滑动。

    窗口内的字节可以分成多个报文,如果最左侧的报文丢包,窗口该怎么滑动?中间的报文丢包呢?最右侧的呢?

    最左侧的报文丢包了:

    如果最左侧报文丢包了,接收方只收到了中间和最右侧的报文,那么应答报文的确认序号是最左侧报文的序号。

    比如发送方发送了四个报文,第一个(即最左侧)报文的字节范围为 1001 ~ 2000(序号为1001),第二个报文的字节范围为 2001 ~ 3000(序号为2001),第三个报文的字节范围为 3001 ~ 4000(序号为3001),第四个报文的字节范围为 4001 ~ 5000(序号为 4001),第一个报文丢包了,但收到了第二、三、四个报文的应答,那么这些应答报文的确认序号一定是 最左侧报文的序号,即 1001。

    接收方发现第一个报文丢包了,那么第二、三、四个报文的应答报文的确认序号只能是 1001,不能是 2001,确认序号为 2001 表示接收方收到了序号为 1 ~ 2000 的字节,但是接收方并没有收到序号为 1001 ~ 2000 的字节。如果此时的应答报文的确认序号为 2001,那么窗口右移了,接收方再也收不到序号为 1001 ~ 2000 的字节,TCP 的可靠性就无法保证了。

    发送方在收到确认序号为 1001 的应答报文之后,就知道接收方没有收到序号为 1000 的报文,即最左侧报文,发送方就会对该报文进行重传,TCP 的可靠性得到了保证。当收到最左侧报文的应答后,窗口才会右移。

    在这个例子中,发送方收到了三个应答报文的确认序号都是 1001,就立即重传该报文,而不是等到超时重传的时间到了,才重传该报文,这种重传方式称为快重传。

    快重传

    当发送方连续收到三个或更多针对同一个数据包的确认(即三次ACK 的确认序号都是一样的),它会立即重传被丢失的数据包。而不是等到超时重传的时间过了,再对丢失的报文进行重传,这样做可以显著减少因为等待定时器而造成的延迟。

    最左侧报文没丢,但中间或者最右侧的报文丢包了:

    有了最左侧报文丢包了的分析后,最左侧报文没丢,但中间或者最右侧报文的丢包情况就容易多了。

    中间的报文丢包了,但是最左侧报文没丢,那么窗口就会右移,随着窗口的右移,中间的报文就会变成最左侧的报文,按照最左侧的报文的丢包来处理。

    最右侧的报文丢包了,但是最左侧和中间的报文没丢包,窗口也会右移,使最右侧报文变成最左侧报文,按照最左侧报文的丢包来处理即可。

    所以这三种情况的丢包,最后都会变成解决最左侧丢包,即使是混合情况的丢包,比如最左侧和中间丢包了,或者最左侧和最右侧丢包了,最后也是变成解决最左侧丢包。

    应答丢包了:

    如果接收方收到了最左侧报文,但是最左侧报文的应答丢了,收到了中间或者最右侧报文的应答,那么不需要重传最左侧报文的应答。

    还是以这个图来举例子,第一个报文的应答报文的确认序号为 2001,接收方收到了第一、二、三、四个报文,发送方只收到了第二、三、四个报文的应答,这些收到的应答报文的确认序号是 5001,那就表示接收方收到了序号为 1 ~ 5000 的字节,那第一个报文的确认序号收没收到也无所谓了,因为后续应答的确认序号已经包括了前面应答的确认序号。

    中间报文的 ACK 报文丢了也没关系,可以通过后续的 ACK 报文来确认。

    所以允许部分 ACK 报文的丢包,因为可以通过后续的 ACK 报文来确认。

    按序处理

    接收方在收到报文时,会把报文按照序号从小到大排序,排序后再把报文拷贝到接收缓冲区中,接收方再按序处理。

    如果接收方能够按序处理报文,则它只需针对最后一个连续的字节序列号发送一个ACK即可。但如果报文乱序到达,接收方可能需要为每一个缺失的序列号发送重复的ACK,或者采用更复杂的策略来通知发送方哪些部分已经收到、哪些部分丢失或乱序,这样会增加网络通信的复杂性和负担。

    版权声明:

    本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

    我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com