云计算百科
云计算领域专业知识百科平台

【计算机网络 | 第八篇】计网之传输层(二)—— TCP的可靠传输与流量控制

⭐️在这个怀疑的年代,我们依然需要信仰。

个人主页:YYYing.

⭐️计算机网络系列专栏:

【从零开始的计算机网络】

⭐️其他专栏:【linux基础】【数据结构与算法】

系列上期内容:【计算机网络 | 第七篇】计网之传输层(一)

系列下期内容:暂无


前言:

        在上一篇中我们讲完了传输层的一部分内容,我们了解了传输层概述与传输层协议的内容含义,那么这一篇我将会带领大家一起学习我们的TCP的可靠传输与流量控制

        (我们此专栏目前会使用的软件是——Wireshark,如有需求,请移至此处官网进行下载,如有问题,请在评论区留言)

TCP可靠传输

一、停止等待ARQ协议

        有些教课书上可能把这块放在链路层去讲,确实没错,可靠性的保证目前确实是在链路层和传输层实现的,但不可能实在网络层,这点了解即可。

●  ARQ(Automatic Repeat–reQuest)自动重传请求

        可以看到,左边的图就跟我们上一篇博客讲的一样,我A端发给B端,然后B端再确认回给A端。但大家有没有想过,我们网络处理数据的时间大概是毫秒级别的,但我们cpu处理数据的时间可是纳秒级别的,那我们在发送后等待确认的过程中,这个浪费的时间虽然对我们人来说无所谓,但对cpu来说可是浪费了6个往上的数量级的时间。当然这点我只是提个醒,而且我们后面也再会提到这个。

        那我们现在来看右边的图,我们可以看到,此时我们发现我们A没有将包发给B,当然,A肯定不知道是他没发给B,还是B没回给A,但我们A也不会管这些,而他只要看到B的包超时后还没发过来,那就自动会重传,那这个重传的时间肯定也会比我们原本正常发送确认的时间要长

●  但若有个包重传了N次还是失败,会一直持续重传到成功为止吗?        ○  取决于系统的设置,重传5次还未成功就会发送RST报文,断开连接

        我们还有其他可能出现的错误,比如下图:

        我们可以看到下图左边对比上图的区别其实就是,B有没有收到,而A是肯定没收到,此时我们A重传后,区别于上图的就是我们会让B把之前A给的M1包丢掉,然后重传确认M1

        那么我们右边就是属于B的确认包实在太慢了,此种情况我们A会直接忽视。

        我们整个ARQ协议看起来像是一个效率很低的协议,但他其实把我们的这个流程也就是所有可能性也都想到了,千言万语汇成一句话其实就是——超时重传。

二、连续ARQ协议 + 滑动窗口协议

        这个就是我们考虑到单一个ARQ协议效率过低,所以我们在此基础上又加了滑动窗口协议,提高了我们的效率

        普通的ARQ就单纯只是一个一个数据段的发,而不难发现我们滑动窗口协议非常好的解决了这个问题,也就是我们弄一个发送窗口,使其装满n个数据段,然后再一次性发送,并等待确认。

        那这块的窗口大小怎么定呢?是A自己定吗?其实自己想想就会觉得应该是B来定,因为我们B是接受端,我们A能发过去这么多数据的前提是B能接受这么多数据,那么对于B的接受能力其实在建立连接的过程中B就已经告诉了A,而在中途中,我们A的滑动窗口也随B的要求可以变化。

        我们现在来个大家抓个包看一下,可以看到这是一个大小为32字节的TCP报文段,也就是说此报文段的选项字段是有内容的,而我们的窗口大小的字段就在我们的选项字段中,可以看此时说的MSS,也就是最大段尺寸是1460字节。


        我们讲完正常的之后,我们现在来看看异常情况。

●  如果接收窗口最多能接4个包,但发送方只发了2个包

       ○  接收方等待一段时间后,没有收到第3个包,就会返回确认收到2个包给发送方

●  每个包多大,每个确认编号如何编址

●  序号和确认号

       ○  依旧是在传输过程的每一个字节都会有一个编号

       ○  在建立连接后,序号表示:这一次传给对方的TCP数据部分的第一个字节的编号

       ○  在建立连接后,确认号表示:期望对方下一次传过来的TCP数据部分的第一个字节的编号

        其实序号和确认号就跟之前没啥区别了,此处当复习即可;

        我们看此图,1>  B告诉A接收窗口是400字节,A就设置发送窗口为400字节,然后我们就按照一个包一个包的编号,然后就发过去。2>  发过去之后就可以看到,我们的接受应用程序会读取接受缓存区里的数据,当然也是按照接收窗口的大小来读,当读完后,就会发现我们的接受窗口就移动到下一个地方了,这也是读完后的标志,然后我们接收端就会回ack。3>  发送端收到确认包后发送端就将之前的分组从缓存区中删除。然后进行窗口滑动和调整窗口,并且我们发送应用程序也在不断的往缓存区里写入东西。最后我们继续按照确认包的确认号组成序号进行发送。4>  我们窗口在滑的过程中发现少了第7个包后,我们就要发一个确认包,让发送方把第7个包补发过来,且会说明已经收到第8个包。5>  然后发送方就会把该包发过去,然后按照窗口的位置继续发送。(这里怕有些人误会,这里的图中7包是在最低下的,但其实这个位置跟发送先后没关系,按理来说7包甚至是最早发的,放在下面只是好写注释)那么后面就不断地按照流程去做就完了。

        但这里的图其实把我们下一部分要讲的东西暗示了,也就是在补发的时候,图中是没有补发第8个包的,但在这其实是要发的,但我们能不能不发呢,这样是不是效率大大的提高了,能的,兄弟能的,答案就是选择确认机制(SACK)

三、选择性确认(SACK)

        在TCP通信过程中,如果发送序列中间某个数据包丢失(比如上图中的7丢失了),TCP会通过重传最后确认的分组后续的分组(最后确认的是6,会重传7,8,9,10),这样原先已经正确传输的分组也可能重复发送(比如8),降低了TCP性能。

●  发展出了SACK(Selective acknowledgment,选择性确认)技术

       ○  告诉发送方哪些数据丢失,哪些数据已经提前收到

       ○  使TCP只重新发送丢失的包(比如7),不用发送后续所有的分组(比如8)

●  SACK信息会放在TCP首部的选项部分

       ○  Kind:占1字节。值为5代表这是SACK选项

       ○  Length:占1字节。表明SACK选项一共占用多少字节

       ○  Left Edge:占4字节,左边界

       ○  Right Edge:占4字节,右边界

        可以看到,下图我们棕色方块的都是已经收到的数据段,而白色是丢包的,比如我们201~300的包没了,那么右边界和左边界分别就是201和301,也就是左闭右开的一个区间,然后让我们接受端去看这个信息,而上图就是我们的存储左右边界的格式。

        那能无限制的存吗,那显然是不能的,一方面我们选项字段没有那么多空间,另一方面丢失太多包本身就说明该连接质量较差,还不如RST重连。

●  一对边界信息需要占用8字节,由于TCP首部的选项部分最多40字节

       ○  SACK选项最多携带4组边界信息

       ○  SACK选项的最大占用字节数 = 4 * 8 + 2 = 34

        我们来看下图是怎么发的,前两条的 len = 0 可能只是在交换信息,真正开始发的是第三条信息,如果前面学的还不错,这块应该看起来是没什么问题的,我们一次性发了5个包,然后最终的确认号是5433,然后接受端发确认包,发送端收到后继续发包,最终到导数第4行的那个包就发完了。

●  思考问题

       ○  为什么刚才我们抓包的时候看到我们的滑动窗口最大尺寸是1460字节?

        我们数据是在数据链路层上传的,那么链路层以太网头中会有个MTU,这个MTU是<=1500的,那这1500怎么构成的,网络层的协议头也就是IP头一般来说就是20字节的固定部分,而我们传输层一般也是20字节的固定字段,1500 – 40 =1460 。也就是说,保证所有保证报文段最小的情况下,我们数据最大就是1460了。当然有人会说刚才不是有头吗,为啥还是会是1460,那你仔细想想这个1460是给谁看的,是不是接收端给发送端看的,若发送端拿到这个包后,它只是按照这个规则去发而已。

       ○  为什么选择在传输层将数据分成多个段,而不是等到网络层分片传递给数据链路层?

        如果传输层的数据包不分包,你们不妨想想会有什么问题,是不是一旦丢包后,整个传输层的数据我们全部都要重传,这样我们重传的效率会很慢,当然太小也会有问题。

        那为什么网络层要分包?

        因为有些场合是要求我们直接将包发给网络层的,比如ICMP,若我们网络层不分包就会遇到像刚才一样的套娃问题,就是我们链路层也需要分,网络层不分也会影响到效率问题。

TCP流量控制

        应用程序可能正忙于其他任务,并不一定能够立刻取走数据。发送端持续发送大量数据,接收端缓存会溢出,造成数据丢失。

        所以TCP为应用程序提供了流量控制(Flow Control)机制,以解决因发送方发送数据太快而导致接收方来不及接收,造成接收方的接收缓存溢出的问题

一、基本情况

●  流量控制的基本方法:接收方根据自己的接收能力(接收缓存的可用空间大小)控制发送方的发送速率。

       ○  通过确认报文中窗口字段来控制发送方的发送速率

       ○  发送方的发送窗口大小不能超过接收方给出窗口大小

       ○  当发送方收到接收窗口的大小为0时,发送方就会停止发送数据

        如果上面的内容都能看懂,那么下图应该问题不会太大,自己可以下去看看,熟悉熟悉。在此只说下最后一块,就是窗口大小从0扩到400后发给A端,A端是会继续传的。

二、特殊情况

        一开始,接收方给发送方发送了0窗口的报文段,后面,接收方又有了一些存储空间,给发送方发送的非0窗口的报文段丢失了,发送方的发送窗口一直为零,双方陷入僵局。

解决方案:

       ○  当发送方收到0窗口通知时,这时发送方停止发送报文

       ○  并且同时开启一个定时器,隔一段时间就发个测试报文去询问接收方最新的窗口大小

       ○  如果接收的窗口大小还是为0,则发送方再次刷新启动定时器

三、小练习

        我们先看甲乙约定的每个数据段最大为1000字节,而窗口为4000字节,也就是说,我们甲现在是要向乙一次性发了4个1000的包,但连续发了两个最大段后(也就是说还有两个1000没发)但由于乙在接收到甲的第一个包后发现自己缓存区内存不够用了,那么就会向甲发一个确认包并将窗口缩小为2000字节,此时因为在甲给乙发第二个包后,窗口刚好框柱了第二个包,此时缩小为2000字节了,那么就说明2000字节的窗口框柱了第二个包和第三个包,那么我们就只能发第三个包了,因为第二个包已经发过了,所以答案就是A。

        主机甲和主机乙之间建立了一个TCP连接,TCP最大段长度为1000字节。若主机乙的当前接收窗口为4000字节,在主机甲向主机乙连续发送两个最大段后,成功收到主机乙发送的第一个段的确认段,确认段中通告的接收窗口大小为2000字节,则此时主机甲还可以向主机乙发送的最大字节数是(         )。

A. 1000                 B. 2000                 C. 3000                 D. 4000

结语

那么关于计网之传输层第二部分有关TCP可靠传输与流量控制的讲解就到这里了。

我是YYYing,后面还有更精彩的内容,希望各位能多多关注支持一下主包。

无限进步,我们下次再见。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 【计算机网络 | 第八篇】计网之传输层(二)—— TCP的可靠传输与流量控制
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!