linux从青铜到王者第十九篇:linux网络基础第二篇之滑动窗口流量控制拥塞控制延迟应答捎带应答

森明帮大于黑虎帮 森明帮大于黑虎帮     2022-12-20     524

关键词:

系列文章目录



前言


👮一、滑动窗口

💰一、滑动窗口的由来

TCP以1个段为单位,每发一个段进行一次确认应答的处理。这样的传输方式有一个缺点。那就是,包的往返时间越长通信性能就越低。

刚才我们讨论了确认应答策略, 对每一个发送的数据段, 都要给一个ACK确认应答.,收到ACK后再发送下一个数据段。这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候。

既然这样一发一收的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)为解决这个问题,TCP引入了窗口这个概念。即使在往返时间较长的情况下,它也能控制网络性能的下降。如图所示,确认应答不再是以每个分段,而是以更大的单位进行确认时,转发时间将会被大幅度的缩短。也就是说,发送端主机,在发送了一个段以后不必要一直等待确认应答,而是继续发送。

  • 窗口大小就是指无需等待确认应答而可以继续发送数据的最大值。图中,窗口大小为4个段,也就是4000个字节。
  • 发送前四个段的时候, 不需要等待任何ACK, 直接发送。
  • 收到第一个ACK后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推。
  • 操作系统内核为了维护这个滑动窗口, 需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉。
  • 窗口越大, 则网络的吞吐率就越高。


这种机制就被称为滑动窗口机制。

再具体一点就是:

💰二、滑动窗口存在的问题

💷1.滑动窗口的大小

💷2.数据包已经传输给对方,但是对方返回的ACK数据包丢失

数据包已经抵达, ACK被丢了。

这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认。

💷3.传输的数据包直接丢失,或者说是某个报文段丢失的情况


  • 当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 "我想要的是 1001开始的数据"一样。
  • 如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数据 1001 - 2000 重新发送。
  • 这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中。


这种机制被称为 “高速重发控制”(也叫 “快重传”)。

🎒二、流量控制

接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送,就会造成丢包, 继而引起丢包重传等等一系列连锁反应。因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制(Flow Control);

  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段, 通过ACK端通知发送端。

  • 窗口大小字段越大, 说明网络的吞吐量越高。

  • 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端。

  • 发送端接受到这个窗口之后, 就会减慢自己的发送速度。

  • 如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端。

接收端如何把窗口大小告诉发送端呢? 回忆我们的TCP首部中, 有一个16位窗口字段, 就是存放了窗口大小信息;那么问题来了, 16位数字最大表示65535, 那么TCP窗口最大就是65535字节么?

实际上, TCP首部40字节选项中还包含了一个窗口扩大因子M, 实际窗口大小是 窗口字段的值左移 M 位。

🎅 三、拥塞控制


虽然TCP有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题。
因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据,是很有可能引起雪上加霜的。
TCP引入 慢启动 机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据。

  • 此处引入一个概念程为拥塞窗口。

  • 发送开始的时候, 定义拥塞窗口大小为1个数据段(1MSS)。

  • 每次收到一个ACK应答, 拥塞窗口加1。

  • 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的滑动窗口大小做比较, 取较小的值作为实际发送的窗口。

  • 像上面这样的拥塞窗口增长速度, 是指数级别的. “慢启动” 只是指初使时慢, 但是增长速度非常快。
  • 为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍。
  • 此处引入一个叫做慢启动的阈值。
  • 当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长。
  • 当TCP开始启动的时候, 慢启动阈值等于窗口最大值。
  • 在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回1。

少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞,当TCP通信开始后, 网络吞吐量会逐渐上升,随着网络发生拥堵, 吞吐量会立刻下降。


但是这种拥塞窗口的大小一旦到达网络拥塞的情况时,拥塞窗口的大小会直接一下子变为慢启动时的阈值,即1个MSS,但是这种情况其实是不科学的,因为我一次丢包有可能是正常的,这种正常的情况的发生有可能是网络闪断了,当网络闪断的时候,拥塞串口的大小就会被置为1,然后再慢启动,再进行拥塞控制,针对这种情况,我们就需要一种快恢复的机制。

总结一下,TCP为了实现拥塞控制,总共采用了慢启动机制、拥塞避免机制、快重传机制和快恢复机制。

🔔四、延迟应答

接收数据的主机如果每次都立刻回复确认应答的话,可能会返回一个较小的窗口。那是因为刚接收完数据,缓冲区已满。

当某个接收端收到这个小窗口的通知以后,会以它为上限发送数据,从而又降低了网络的利用率(这其实是窗口控制特有的问题,专门术语叫做糊涂窗口综合征)。为此,引入了一个方法,那就是收到数据以后并不立即返回确认应答,而是延迟一段时间的机制。

  • 假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;
  • 但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了。
  • 在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来。
  • 如果接收端稍微等一会再应答, 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M。

窗口越大, 网络吞吐量就越大, 传输效率就越高. 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率.。那么所有的包都可以延迟应答么? 肯定也不是;

  • 数量限制: 每隔N个包就应答一次。
  • 时间限制: 超过最大延迟时间就应答一次。

具体的数量和超时时间, 依操作系统不同也有差异,一般N取2,超时时间取200ms。

🎉五、捎带应答


在延迟应答的基础上, 我们发现, 很多情况下, 客户端服务器在应用层也是 “一发一收” 的. 意味着客户端给服务器说了 “How are you”, 服务器也会给客户端回一个 “Fine, thank you”; 那么这个时候ACK就可以搭顺风车, 和服务器回应的 “Fine, thank you” 一起回给客户端。

接收数据以后如果立刻返回确认应答,就无法实现捎带应答。而是将所接收的数据传给应用处理生成返回数据以后进再进行发送请求为止,必须一直等待确认应答的发送。也就是说,如果没有启用延迟确认应答就无法实现捎带应答。延迟确认应答是能够提高网络利用率从而降低计算机处理负荷的一种较优的处理机制。

⏰六、保活机制

🚿七、延迟发送机制


💬总结

以上就是今天要讲的内容,本文详细介绍了传输层TCP协议保证传输效率和可靠传输的方法,网络提供了大量的方法供我们使用,非常的便捷,我们务必掌握。希望大家多多支持!另外如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。加油啊!

linux从青铜到王者第十四篇:linux网络基础第一篇

系列文章目录文章目录系列文章目录前言一、计算机网络的发展过程1.独立模式2.网络互联模式3.局域网LAN4.广域网WAN二、认识计算机网络协议1.协议的概念2.什么是网络协议3.网络协议簇4.体系结构5.OSI七层模型6.TCP/IP五层(或四层)... 查看详情

linux从青铜到王者第十八篇:linux网络基础第二篇之tcp协议

系列文章目录文章目录系列文章目录前言一、TCP面向字节流二、TCP粘包问题1.什么是TCP粘包问题2.TCP粘包问题的解决办法三、TCP异常情况四、TCP协议1.TCP协议段格式2.确认应答(ACK)机制3.超时重传机制4.连接管理机制1、TCP三次握手1.... 查看详情

linux从青铜到王者第十七篇:linux网络基础第二篇之udp协议

系列文章目录文章目录系列文章目录前言一、传输层1.再谈端口号2.端口号范围划分3.认识知名端口号(Well-KnowPortNumber)4.进程和端口号两个问题5.netstat查看网络状态二、UDP协议1.UDP协议端格式2.UDP的特点3.面向数据报4.UDP的缓冲区5.UDP... 查看详情

linux从青铜到王者第十五篇:linux网络编程套接字两万字详解(代码片段)

系列文章目录文章目录系列文章目录前言一、网络数据的五元组信息1.理解源IP地址和目的IP地址2.理解"端口号"和"进程ID"3.理解源端口号和目的端口号4.理解TCP协议5.理解UDP协议二、主机字节序<===>网络字... 查看详情

linux从青铜到王者第十六篇:linux网络基础第二篇之http协议(代码片段)

系列文章目录文章目录系列文章目录前言一、HTTP协议的概念二、HTTP协议URL的解释三、HTTP协议的数据流四、HTTP协议格式1.HTTP请求2.HTTP响应五、HTTP协议格式图解六、HTTP协议版本七、HTTP协议请求方法1.GET:获取资源2.POST:... 查看详情

linux从青铜到王者第十二篇:linux进程间信号第二篇(代码片段)

系列文章目录文章目录系列文章目录前言一、阻塞信号1.信号其他相关常见概念2.在内核中的表示3.sigset_t信号集4.信号集操作函数5.sigprocmask函数6.sigpending函数二、捕捉信号1.内核实现信号的捕捉2.volatile关键字总结前言一、阻塞信... 查看详情

linux从青铜到王者第十三篇:linux多线程四万字详解(代码片段)

系列文章目录文章目录系列文章目录前言一、Linux线程概念1.什么是线程2.线程的优点3.线程的缺点4.线程的异常5.线程的用途二、进程和线程的对比1.进程和线程2.多进程的应用场景有哪些?三、线程控制1.POSIX线程库2.创建线程... 查看详情

linux从青铜到王者第二十篇:linux网络基础第三篇之ip协议

系列文章目录文章目录系列文章目录前言一、IP协议基本概念二、IPv4首部三、网络号和主机号四、早期地址管理方式五、CIDR(ClasslessInterdomainRouting)方式六、特殊的IP地址七、IP地址的数量限制八、路由控制总结前言一、IP协议基本... 查看详情

linux从青铜到王者第二十四篇:linux网络基础第四篇之websocket协议(代码片段)

系列文章目录文章目录系列文章目录前言一、WebSocket简介二、WebSocket产生背景三、WebSocket实现原理四、WebSocket协议举例五、WebSocket使用1.WebSocket介绍2.WebSocketAPI3.WebSocket事件1.open2.Message3.Error4.Close4.WebSocket方法1.send()2.close()5.WebSocket... 查看详情

linux从青铜到王者第二十一篇:linux网络基础第三篇之数据链路层

系列文章目录文章目录系列文章目录前言一、数据链路层的以太网协议二、认识MAC地址三、对比理解MAC地址和IP地址四、ARP协议的作用五、ARP数据报格式五、ARP协议工作流程六、ARP缓存表七、DNS(DomainNameSystem)八、NAT协议九、NAPT协... 查看详情

c++从青铜到王者第九篇:stl之vector类的初识(代码片段)

系列文章目录文章目录系列文章目录前言一、vector的介绍1.vector的介绍二、vector的使用1.vector的定义2.vectoriterator的使用3.vector空间增长问题4.vector增删查改三、vector迭代器失效问题。总结前言一、vector的介绍1.vector的介绍vector文档... 查看详情

lua从青铜到王者基础篇第十三篇:lua调试(debug)(代码片段)

系列文章目录文章目录系列文章目录前言🌲一、Lua调试(Debug)🌳二、另一个实例🌴三、调试类型💬🌲🌳🌴🌵总结前言🌲一、Lua调试(Debug)Lua提供了debug库用于提供创建我们自定义调试器的功... 查看详情

从青铜到王者,你只差这篇全网最全linux命令大全

〝古人学问遗无力,少壮功夫老始成〞从青铜到王者,你只差这篇全网最全linux命令大全。全网最全linux命令大全,从入门到精通,助力大厂橄榄枝,如果这篇文章能给你带来一点帮助,希望给飞兔小哥哥... 查看详情

从青铜到王者,你只差这篇全网最全linux命令大全

〝古人学问遗无力,少壮功夫老始成〞从青铜到王者,你只差这篇全网最全linux命令大全。全网最全linux命令大全,从入门到精通,助力大厂橄榄枝,如果这篇文章能给你带来一点帮助,希望给飞兔小哥哥... 查看详情

linux篇第十九篇——网络套接字编程(tcp套接字的编写+多进程版本+多线程版本+线程池版本)(代码片段)

⭐️本篇博客开始给大家介绍网络编程中的套接字编程——基于UDP协议的套接字和基于TCP的套接字,这篇博客主要介绍基于UDP协议套接字,下一篇介绍基于TCP协议的套接字。在介绍套接字编程之前,我会先给大家介绍... 查看详情

linux从青铜到王者第二十二篇:linux高级io(代码片段)

系列文章目录文章目录系列文章目录前言一、五种IO模型1.阻塞IO2.非阻塞IO3.信号驱动IO4.异步IO5.IO多路转接二、高级IO重要概念1.同步通信vs异步通信2.阻塞vs非阻塞三、I/O多路转接之select1.select函数的作用2.select函数的原型3.fd_set结... 查看详情

c++从入门到入土第十九篇:二叉搜索树(代码片段)

二叉搜索树文章目录二叉搜索树二叉搜索树概念原理性质复杂度二叉搜索树操作1.结构2.查找3.插入4.中序遍历5.拷贝6.销毁7.删除二叉搜索树概念二叉查找树(BinarySearchTree),(又:二叉搜索树,二叉排序树... 查看详情

c++从青铜到王者第十八篇:c++之多态(代码片段)

系列文章目录文章目录系列文章目录前言一、多态的概念1.多态的概念二、多态的定义及实现1.多态的构成条件2.虚函数的认识3.虚函数的重写1.虚函数重写的两个例外之协变2.虚函数重写的两个例外之析构函数的重写4.C++11ove... 查看详情