【计算机网络】数据链路层(上)

导读:本篇文章讲解 【计算机网络】数据链路层(上),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

也许你感觉自己的努力总是徒劳无功,但不必怀疑,你每天都离顶点更进一步。今天的你离顶点还遥遥无期。但你通过今天的努力,积蓄了明天勇攀高峰的力量。加油!

数据链路层概述

首先我蛮来看看数据链路层在网络体系结构中的地位。如图所示主机h1给主机h2发送数据,中间要经过三个路由器和电话网、局域网以及广域网等多种网络。
在这里插入图片描述
从5层协议原理体系结构的角度来看,主机应具有体系结构中的各个层次,而路由器只需具有体系结构中的下面三层,各设备通过物理层下面的传输媒体进行互联,当主机h1向h2发送数据时,数据的流动如图所示:

  • 主机h1将在发送的数据逐层封装后,通过物理层将构成数据包的个比特转换为电信号,发送到传输媒体,数据包进入路由器后,由下往上逐层解封到网络层。
  • 路由器根据数据包的目的网络地址和自身转发表,确定数据包的转发端口,然后从网络层向下逐层封装数据包,并通过物理层将数据包发送到传输媒体
  • 数据包最终到达主机h2时,还要由下往上逐层解封,最终解封出主机h1所发送的数据。

当我们专门研究数据链路层的问题时,在大多数情况下,我们可以只关心数据链路层,而不考虑网络体系结构的其他各层。换句话说,我们可以想象数据包只在数据链路层,从左向右沿水平方向传送。从数据链路层来看,主机h1到h2的通信,可以看成是在4段不同的链路上的通信组成的:
在这里插入图片描述
所谓链路就是从一个节点到相邻节点的一段物理线路,中间没有任何其他的交换节点

要在链路上传输数据,仅有链路还不够,还需要一些通信协议来控制这些数据的传输。若把实现这些协议的硬件和软件加到电路上,就构成了数据链路

在数据链路层上传输的数据包又称为,也就是说数据链路层以帧为单位传输和处理数据

接下来我们介绍数据链路层的三个重要问题,他们是:

  • 封装成帧
  • 差错检测
  • 可靠传输

封装成帧

先来看封装成帧。如图所示,两台主机通过一段链路互联,两台主机都会对所发送或接收的数据包进行5个层次的封装或解封。

在这里插入图片描述
过程如下:

  • 发送方将待发送的数据通过应用层封装成为应用层协议数据单元,然后交付给运输层,
  • 运输层为其添加运输层协议首部,使之成为运输层协议数据单元,然后交付给网络层,
  • 网络层为其添加网络层协议首部,使之成为网络层协议数据单元,然后交付给数据链路层,
  • 数据链路层给网络层协议数据单元,添加一个数据链路层协议首部简称为帧头,还要给其添加一个帧尾。
  • 我们将数据链路层给网络层交付的协议数据单元,添加帧头和帧尾的操作称为封装成帧添加帧头和帧尾的目的都是为了在链路上以帧为单元来传送数据,也就是为了实现数据链路层本身的功能
  • 例如上图是以太网版本2的MAC帧格式,这三个字段是帧头,最后一个字段是帧尾,中间的字段是上层交付的协议数据单元。

差错检测

发送方将封装好的帧通过物理层发送到传输媒体,帧在传输过程中遭遇干扰后可能会出现误码,也就是比特0可能变成了比特1,反之亦然。
在这里插入图片描述

那么接收方主机如何判断帧在传输过程中是否出现了误码?

这可以通过检错码来发现

发送方在发送帧之前,基于待发送的数据和检错算法,计算出检错码,并将其封装在帧尾。例如以太网版本2的MAC帧的帧尾,就是4字节的帧检验序列FCS字段。要写入该字段的内容,也就是我们所说的检错码:
在这里插入图片描述

接收方主机收到帧后,通过检错码和检错算法,就可以判断出真在传输过程中是否出现了误码。
在这里插入图片描述

可靠传输

接收方主机收到有误码的帧后,是不会接受该帧的,而是将其丢弃

  • 如果数据链路层向其上层提供的是不可靠服务,那么丢弃就丢弃了,不会再有更多措施。
  • 如果数据链路层向其上层提供的是可靠服务,那么就还需要其他措施来确保接收方主机还可以重新收到被丢弃的帧的正确副本。

换句话说,尽管误码是不能完全避免的,但若能实现发送方发送什么,接收方最终都能收到什么,就称为可靠传输

封装成帧,差错检测,可靠传输是数据链路层中最基本最重要的问题。我们在后文中还会详细介绍。

前面我们说的都是点对点信道的数据链路层,但是对于对于使用广播信道的数据链路层,除了包含这三个问题外,还有一些其他需要解决的问题。

在这里插入图片描述
如图所示,主机abcde通过一根总线进行互联,主机a要给主机c发送帧,代表帧的信号,会通过总线传输到总线上的其他各主机,那么主机bde如何知道所收到的帧不是发送给他们的,而主题c又如何知道所收到的帧恰恰是发送给自己的,相信大家能够想到地址或者说编制的问题,也就是将帧的目的地址添加在帧中一起传输。

例如以太网版本2的MAC帧格式,其首部中的三个字段中有两个字段和地址相关,一个是目的地址字段,另一个是源地址字段。

除了编制问题外,再来看下面这个问题,当总线上多台主机,同时使用总线来传输帧时,传输信号就会产生碰撞,这是采用广播信道的共享式局域网不可避免的。以太网采用的协调方法是使用一种特殊的协议,CSMA/CD,也就是载波监听多点接入/碰撞检测。
在这里插入图片描述
随着技术的发展,交换技术的成熟和成本的降低,具有更高性能的需要点对点联络和链路层交换机的交换式局域网,在有线领域已完全取代了共享式局域网,那么网络中的交换机又是如何转发帧的,另外由于无线信道的广播天性,无线局域网仍然使用的是共享信道技术,例如802.11局域网采用的媒体接入控制协议是CSMA/CA,也就是载波监听多点接入/碰撞避免,它的工作原理又是怎样的,上述这些内容都是数据链路层中比较重要的问题
在这里插入图片描述

总结一下,本文我们将会涉及到以下几点:
在这里插入图片描述

封装成帧

所谓封装成帧就是指数据链路层给上层交付下来的协议数据单元,添加帧头和帧尾,‍‍使之成为帧

例如下图所示在帧头和帧尾中包含有重要的控制信息,下图分别显示了以太网版本V2的MAC帧格式,以及点对点协议PPP的帧格式
在这里插入图片描述
发送方的数据链入层将上层交付下来的协议数据单元封装成帧后,还要通过物理层‍‍将构成帧的个比特转换成电信号,发送到传输媒体。‍‍那么接收方的数据链路层‍‍如何从物理层交付的比特流中提取出一个个的帧呢实际上‍‍帧头和帧尾的作用之一就是帧定界
在这里插入图片描述
例如以下是PPP帧的格式,在其帧头和帧尾中‍‍各包含有一个长度为1字节的标志字段,其作用就是帧定界。假设发送方发送的是PPP帧,‍‍比特流中红色部分是帧定界标志,那么接收方的数据链路层就可以依据帧定界标志,‍‍从物理层交付的比特流中提取出一个个的帧
在这里插入图片描述

需要说明的是‍‍并不是每一种数据链路层协议的帧都包含有帧定界标志。‍‍

例如下图是以太网版本2的MAC帧格式,‍‍在其帧头和帧尾中并没有包含帧定界标志。那么接收方又是如何从物理层交付的比特流中‍‍提取出一个个的以太网帧?

实际上以太网的数据链路层封装好MAC帧后将其交付给物理层,‍‍物理层会在MAC帧前面添加八字节的前导码,然后再将比特流转换成电信号发送‍‍。前导码中的前7个字节为‍‍前同步码,作用是使接收方的时钟同步,之后的1字节为帧开始定界符,‍‍表明其后面紧跟着的就是MAC帧。‍‍
在这里插入图片描述
另外以太网还规定了帧间间隔时间为‍‍96比特的发送时间,因此MAC帧并不需要帧结束定界符,需要说明的是‍‍帧间间隔还有其他作用,我们在以后还会提到。‍‍

透明传输

接下来我们介绍透明传输的问题,‍‍透明传输是指数据链路层对上层交付的传输数据并没有任何限制,就好像数据链路层不存在一样。‍‍我们来举例说明,下图使发送方数据链路层收到其上层交付的协议数据单元,给其添加帧头‍‍和帧尾,使其成为帧。‍‍为了简单起见,我们只画出了帧头和帧尾中的帧定界标志,‍‍帧定界标志也就是一个特定数值。
在这里插入图片描述

请大家思考一下,如果在上层交付的协议数据单元中,‍‍恰好也包含了这个特定数值,接收方还能正确接收该帧吗?‍‍

回答是否定的。如图所示,接收方在收到第一个帧定界标志时,认为这是帧的开始,‍‍这并没有错误。‍‍当接收方再次接收到帧定界标志时,会误认为帧结束了:
在这里插入图片描述
如果数据链路层不采取其他措施,来避免接收方对帧是否结束的误判,就不能称为透明传输。‍‍也就是说数据链入层对上层交付的协议数据单元有限制,其内容不能包含帧定界符,‍‍很显然这样的数据链路层没有什么使用价值

实际上各种数据链路层协议一定会想办法来解决这个问题。‍‍例如在发送帧之前,‍‍对帧的数据部分进行扫描,每出现一个帧定界符,就在其前面插入一个转义字符,‍‍接收方数据链路层在物理层交付的比特流装提取帧,遇到第一个帧定界符时,认为这是帧的开始。‍‍当遇到转义字符时就知道其后面的一字节内容虽然与帧定界符相同,但它是数据,‍‍而不是啊定界符剔除转义字符后,将其后面的内容作为数据继续提取。‍‍当再次提取到帧定界符时,表明这是帧的结束。‍‍

在这里插入图片描述
请大家再来思考一下这种情况。在上层交付给数据链路层的协议数据单元中,既包含了帧定界符,‍‍又包含了转义字符,应该怎么处理

方法仍然是在发送帧之前对帧的数据部分进行扫描,‍‍每出现一个帧定界符或转义字符,‍‍就在其前面插入一个转义字符
在这里插入图片描述

需要说明的是转义字符是一种特殊的控制字符,‍‍其长度为一个字节,10进制值为27,而并不是E、S以及C这三个字符。‍‍

我们刚刚介绍的是面向字节的物理链路,是用字节填充或称字符填充的方法‍‍来实现透明传输。‍‍

对于面向比特的电路,应该使用比特填充的方法来实现透明传输

例如‍‍下图某个点对点协议的帧。为了简单起见,在帧手部和尾部中‍‍仅给出了帧定界标志,而未给出其他控制字段,而帧的数据部分出现了两个帧定界标志,‍‍但它们实际上是数据,而不是帧定界。‍‍

我们可以在发送前可以采用0比特填充法,‍‍对数据部分进行扫描,每5个连续的比特1后面就插入1个比特0,‍‍这样就确保了帧定界在整个帧中的唯一性,也就可以实现透明传输。

之所以可以确定唯一性是因为,帧定界标志中有6个1,而我们每5个连续的比特1后面就插入1个比特0,就可以避免重复发生。

在这里插入图片描述

接收方的数据链路层,‍‍从物理层交付的比特流中提取帧时,将帧的数据部分中的每5个连续的比特1后面的比特0剔除即可。‍‍

我们来做一个有关0比特填充的练习题:
在这里插入图片描述

最后还要提醒大家,为了提高帧的传输效率,‍‍应当使帧的数据部分的长度尽可能大一些。‍‍

如图所示帧的数据部分的长度‍‍应远大于帧头和帧尾的程度,这样才能提高帧的传输效率。因为仅从数据链路层来看,‍‍帧的数据部分才是帧正要传输的数据,帧头和帧尾是为了实现数据链路层功能而额外添加的。‍‍当然了,考虑到差错控制等多种因素,每一种数据链路层协议都规定了帧的数据部分的长度上限,‍‍称为最大传送单元MTU

在这里插入图片描述

小结:
在这里插入图片描述

差错检测

我们知道‍‍实际的通信链路都不是理想的,比特在传输过程中可能会产生差错,1可能变成0,‍‍而0也可能变成1,这称为比特差错

如图所示。比特流在传输过程中,‍‍由于受到各种干扰,就可能会出现比特差错或称为误码。‍‍在一段时间内‍‍传输错误的比特占所传输比特总数的比率成为误码率BER

在这里插入图片描述
接收方的数据链路层‍‍又是通过怎样的方法才能知道比特在传输过程中出现了错误呢?

使用差错检测码‍‍来检测数据在传输过程中是否产生了比特差错

  • 例如以太网版本2的MAC帧格式,其帧尾中包含了一个长度为4字节的帧检验序列FCS字段,‍‍其作用就是让接收方的数据链路层检查帧在传输过程中是否产生了误码
  • 点对点协议PPP的帧格式,其帧尾中也包含了一个长度为两字节的帧检验序列,‍‍FCS字段,其作用也是让接收方的数据链路层检查正在传输过程中是否产生了误码

在这里插入图片描述

奇偶校验

接下来‍‍我们介绍奇偶校验这种比较简单的检测方法,在待发送的数据后面添加一位奇偶校验位,‍‍使整个数据包括所添加的校验位在内中的1的个数为奇数这称为奇校验,或为偶数这称为偶校验。‍‍

我们来举例说明:
在这里插入图片描述

  • 换句话说,‍‍采用奇校验,若比特1的数量的奇性改变,可以检查出错误,但是‍‍如果传输过程中产生了两位误码,接收方对收到的比特流进行奇校验,‍‍发现比特1的总数为奇数,就误认为传输过程中没有发生误码。换句话说,采用奇校验,‍‍若比特1的数量的奇性不改变,是无法检查出错误的。‍‍
  • 假设收发双方约定采用偶校验,‍‍那么在数据后面添加的校验位应该为比特0,使得比特1的总数为偶数,‍‍假设传输过程中产生了1位误码,接收方对收到的比特流进行偶校验,‍‍发现比特1的总数为奇数而不是偶数,就知道传输过程中发生了误码。换句话说,采用偶校验‍‍若比特1的数量的偶性改变,可以检查出错误,但是如果传输过程中产生了两位误码,接收方对收到的比特流进行偶校验,发现比特1的总数为偶数,‍‍就误认为传输过程中没有发生误码。换句话说,采用偶校验,若比特1的数量的偶性不改变,‍‍是无法检查出错误的。‍‍

通过本例可以看出采用奇偶校验,如果有奇数个位发生误码,则奇偶性会发生变化,也就是奇变偶者是偶变奇,这样就可以检查出误码。而如果有偶数各位发生误码,则奇偶性不会发生变化,‍‍这是因为每个误码对奇偶性的影响相互抵消了,这样就要无法检查出误码,也称为漏检。‍‍由于奇偶校验的漏检率比较高,因此计算机网络的数据链路层一般不会采用这种检测方法。‍‍

循环冗余校验CRC

接下来我们介绍循环冗余校验CRC,这是一种具有很强检测能力的检测方法,漏检率极低:

  • 收发双方约定好一个生成多项式
  • 发送方基于代发送的数据和生成多项式计算出差错检测码,称为冗余码,‍‍并将其添加到带传输数据的后面一起传输。
  • 接收方通过生成多项式来计算‍‍收到的数据是否产生了误码。

我们来看一下双方的处理过程;
在这里插入图片描述

下面‍‍我们对生成多项式举例说明:
在这里插入图片描述

生成多项式各项系数构成的比特串,就是我们做除法时所用到的除数,‍‍上图是常用的生成多项式,使用这些生成多项式进行crc校验,可以达到较好的检测效果,‍‍也就是漏检率比较低。需要注意的是crc算法要求生成多项式,必须包含最低次项。‍‍

我们来看两道题:
在这里插入图片描述
在这里插入图片描述

我们还要注意:

  • 检错码只能检测出帧在传输过程中出现了差错,但并不能定位错误,因此无法纠正错误。‍‍
  • 要想纠正传输中的差错,可以使用冗余信息更多的纠错码,进行前向纠错,但纠错码的开销比较大,在计算机网络中较少使用。
  • 循环冗余校验crc‍‍有很好的检错能力,漏检率非常低,虽然计算比较复杂,但非常易于用硬件来实现,‍‍因此被广泛应用于计算机网络的数据链路层
  • 在计算机网络中通常采用检错重传方式来纠正传输中的差错,或者仅仅是丢弃检测到差错的帧,‍‍这取决于数据链路层向其上层‍‍提供的是可靠传输服务,还是不可靠传输服务

可靠传输

可靠传输基本概念

我们已经知道使用差错检测技术,例如循环冗余校验crc,‍‍接收方的数据链路层,就可以检测出帧在传输过程中是否产生了误码,也就是出现比特错误。‍‍

如下所示,帧在传输过程中受到干扰,产生了误码。‍‍接收方的数据链路层‍‍通过帧尾中的帧检验序列、FCS字段的值,‍‍也就是检测可以检测出帧中出现了比特差错,那么接下来该如何处理呢?‍‍
在这里插入图片描述

这取决于数据链路层向其上层提供的服务类型:

  • 如果提供的是不可靠传输服务,‍‍则仅仅丢弃有误码的帧,其他什么也不做。

  • 如果提供的是可靠传输服务,那就还要想办法‍‍实现发送端发送什么,接收端就收到什么。

    • 例如接收方可以给发送方发送一个通知帧‍‍,告诉他之前发送的帧产生了误码,‍‍请重发。发送方收到通知后重发之前产生了误码的帧即可。‍‍
    • 实际上可靠传输的实现‍‍并没有我们想象的这么简单。试想一下,这个通知帧如果也出现了误码,又会怎么样?

注意:

  • 一般情况下有线链路的误码率比较低,‍‍为了减小开销,并不要求数据链路层向上提供可靠传输服务,即使出现了误码‍‍,可靠传输的问题,由其上层处理。

  • 然而对于无线链路,由于其容易受到干扰,‍‍误码率比较高,因此要求数据链路层必须向上层提供可靠传输服务。

需要说明的是‍‍比特差错只是传输差错中的一种。‍‍从整个计算机网络体系结构来看,传输差错还包括‍‍分组丢失,分组失序以及分组重复。‍‍请注意,此处我们将帧的称呼改为了分组,这意味着传输差错‍‍不仅仅局限于数据链路层的比特差错。

我们来看一个例子:
在这里插入图片描述

  • 主机h6给主机h2发送的分组,‍‍到达了路由器R5,由于此时R5的输入队列快满了,R5根据自己的分组丢弃策略,‍‍将该分组丢弃,这是一种分组丢失的情况。‍‍

  • 再来看分组失序的例子,‍‍主机h6依次给主机h2发送了三个分组,但他们并未按照发送顺序依次到达H2,‍‍也就是说最先发送的分组‍‍未必最先到达。‍‍

  • 再来看分组重复的例子,主机H6给主机H2发送的分组,由于某些原因‍‍在网络中滞留了没有及时到达H2,这可能造成H6对该分组的超时重发,‍‍重发的分组到达H2一段时间后滞留在网络中的分组又到达了H2,‍‍这就会造成分组重复的传输差错。

分组丢失,分组失序以及分组重复这些传输差错,‍‍一般不会出现在数据链路层,‍‍而会出现在其上层

因此可靠传输服务并不仅局限于数据链路层,‍‍其他各层均可选择实现可靠传输服务。‍‍

在这里插入图片描述

例如上图是tcpip的4层体系结构,‍:

  • 如果网络接口层使用的是802.11无线局域网,那么其数据链路层要求实现可靠传输,‍‍
  • 如果网络接口层使用的是以太网,那么其数据链路层不要求实现可靠传输,
  • 网际层中的IP协议‍‍向其上层提供的是无连接不可靠的传输服务。
  • 运输层中的TCP协议‍‍向其上层提供的是面向连接的可靠传输服务,‍‍而UDP协议向其上层提供的是无连接不可靠的传输服务

最后需要提醒大家注意,‍‍可靠传输的实现比较复杂,开销也就比较大,是否使用可靠传输取决于应用需求。‍‍

小结:
在这里插入图片描述

实现机制 — 停止-等待协议

我们将用下面的篇幅来介绍三种可靠传输的实现机制,它们是停止等待协议SW,回退N帧协议GBN,选择重传协议SR。‍‍需要提醒大家注意的是,这三种可靠传输实现机制的基本原理,并不仅限于数据链路层,‍‍可以应用到计算机网络体系结构的各层协议中

我们先介绍停止等待协议,如下图所示,收发双方基于互联网进行通信,‍‍而不是局限在一条点对点的数据链路,纵坐标为时间。

在这里插入图片描述

  • 发送方给接收方发送数据分组,‍‍接收方收到后对其进行差错检测,

  • 若没有误码,则接受该数据分组,‍‍并给发送方发送确认分组,简称为ack

  • 发送方收到对所发送数据分组的确认分组后,‍‍才能发送下一个数据分组。

我们来看一种情况,如图:
在这里插入图片描述

  • 假设这个数据分组在传输过程中出现了误码,‍‍接收方收到后对其进行差错检测,‍‍发现了误码,则丢弃该数据分组,并给发送方发送否认分组,简称为nak‍‍

  • 发送方收到对所发送数据分组的否认分组后,就知道了之前自己所发送的数据分组出现了差错,‍‍而被接收方拒绝,于是立刻重传该数据分组。‍‍

  • 因此发送方每发送完一个数据分组后,‍‍并不能立刻将该数据分组从缓存中删除,只有在收到帧对该数据分组的确认,分组后‍‍才能将其从缓存中删除。

  • 看来‍‍每发送完一个数据分组后,就停止发送下一个数据分组,‍‍等待来自接收方的确认分组或否认分组。‍‍若收到确认分组,则可继续发送下一个数据分组。‍‍

  • 若收到否认分组,则重发之前发送的数据分组,这样就要实现了发送方发送什么,接收方最终都能收到什么,也就是所谓的可靠传输。

但实际情况远比我们想象的要复杂。‍‍来看这种情况,发送方给接收方发送数据分组,然而该数据分组在传输过程中丢失了,‍

需要说明的是‍‍对于数据链路层点对点信道而言,不太容易出现这种情况,但对于多个网络,通过多个路由器‍‍互联的复杂互联网环境而言,这种情况是会经常出现的。‍‍

对于这种情况,接收方既然收不到数据分组,‍‍那么也就不会无缘无故的发送确认或否认分组。如果不采取其他措施,‍‍发送方就会一直处于等待接收方确认或否认分组的状态

为了解决该问题,‍‍可以在发送方发送完一个数据分组时,启动一个超时计时器。‍‍若到了超时计时器所设置的重传时间,‍‍而发送方仍收不到接收方的确认或否认分组,则重传原来的数据分组,这就叫做超时重传。‍‍一般可将重穿时间选为略大于从发送方到接收方的平均往返时间。

如图所示‍‍发送方超时重传之前所发送的数据分组,接收方正确接收重传的数据分组后,‍‍给发送方发送确认分组,发送方收到确认分组后,发送下一个数据分组,‍‍接收方正确接收该数据分组后,给发送方发送确认分组,到目前为止,‍‍貌似基于停止等待,使用确认或否认分组,再加上超时重传的手段,‍‍就可以实现可靠传输了

在这里插入图片描述
但请大家再深入的思考一下,是否还会出现‍‍目前这些手段不足以应对实现可靠传输的其他情况?来看这种情况。‍‍既然发送方发送的数据分组可能丢失,那么接收方发送的确认或否认分组就也有可能丢失。‍‍例如发送方发送了一个数据分组,接收方正确接收该数据分组后,给发送方发送确认分组,‍‍但该确认分组‍‍在传输过程中丢失了,这必然会造成发送方对之前所发送数据分组的超时重传,‍‍假设重传的数据分组也正确到达了接收方。那么现在问题来了,接收方如何判断‍‍该数据分组是否是一个重复的分组?
在这里插入图片描述

为了避免分组重复这种传输错误,‍‍必须给每个数据分组带上序号。‍‍例如该数据分组的序号为0,对于停止等待协议,‍‍由于每发送一个数据分组,就进行停止等待,只要保证每发送一个新的数据分组,‍‍其序号与上次发送的数据分组的序号不同就可以了。因此用一个比特来编号就够了,即序号0和1,这样根据数据分组的序号,‍‍接收方就可以判断出该数据分组是否是重复的,接收方丢弃重复的数据分组,‍‍并给发送方发送帧对该数据分组的确认分组,以免发送方对该数据分组的再次超时重传。‍‍

发送方收到帧对0号数据分组的确认分组,就可以发送下一个数据分组了,其序号为1,‍‍接收方正确收到1号数据分组后,给发送方发送确认分组,我们通过确认分组丢失的情况,‍‍引出了给数据分组编号的问题。请大家思考一下,既然数据分组需要编号,‍‍那么确认分组是否也需要编号?

我们还是来看一个例子。发送方发送0号数据分组,‍‍接收方正确接收后,给发送方发送确认分组,由于某些原因,该确认分组迟到了,‍‍这必然会导致发送方对0号数据分组的超时重传。‍‍在重传的0号数据分组的传输过程中,‍‍发送方收到了迟到的确认分组,于是发送一号数据分组,接收方收到重传的零号数据分组后,‍‍发现这是一个重复的数据分组,将其丢弃,并针对该数据分组给发送方发送确认分组,‍‍以免发送方再次超时重传该数据分组。‍‍现在问题来了,我们可以非常清楚的看到,‍‍这是一个对0号数据分组的重复确认,但是发送方又如何知道呢?‍‍如果不采取其他措施的话,发送方会误认为这是对1号数据分组的确认,‍‍如果对确认分组也进行编号,就可以使发送方避免这种误判。
在这里插入图片描述

如图所示‍‍该确认分组的序号为0,发送方通过确认分组的序号,知道这是一个重复的确认分组,忽略即可。‍‍接收方正确接受一号数据分组后,给发送方发送帧对该数据分组的确认,分组其序号为一,‍‍发送方收到该确认分组后,发送下一个数据分组,序号为0。‍‍

请注意‍‍该数据分组与之前序号为0的数据分组,不是同一个数据分组,我们用给确认分组编号的方法,‍‍解决了确认迟到所导致的重复确认的问题。需要说明的是‍‍对于数据链路层的点对点信道,往返时间比较固定,不会出现确认迟到的情况。‍‍

因此‍‍如果只在数据链路层实现停止等待协议,可以不用给确认分组编号。‍‍接下来‍‍我们对停止等待协议的一些注意事项进行一下小结:

  • 接收端检测到数据分组有误码时,‍‍将其丢弃,并等待发送方的超时重传。但对于误码率较高的点对点链路,‍‍为使发送方尽早重传,也可给发送方发送否认分组。
  • 为了让接收方能够判断‍‍所收到的数据分组是否是重复的,需要给数据分组编号,由于停止等待协议的停等特性,‍‍只需一个比特编号就够了,即序号0和1
  • 为了让发送方能够判断‍‍所收到的确认分组是否是重复的,需要给确认分组编号,所用比特数量‍‍与数据分组编号所用比特数量一样,数据链路层一般不会出现确认分组迟到的情况,因此‍‍在数据链路层实现停止等待协议,可以不用给确认分组编号,
  • 超时计时器设置的重装时间‍‍应仔细选择,‍‍一般可将重装时间选为略大于从发送方到接收方的平均往返时间。‍‍
  • 在数据链路层点对点的往返时间比较确定,重传时间比较好设定。‍‍然而在运输层,‍‍由于端到端往返时间非常不确定,设置合适的重装时间有时并不容易,我们将在后面有关TCP协议的文章中详细讨论该问题。

接下来我们来看看停止等待协议的信道利用率。‍‍

如图所示,横坐标为时间。为了简单起见,假设收发双方之间‍‍是一条直通的信道,发送方发送完一个数据分组后,就要停止发送,‍‍并等待接收方对该数据分组的确认。当收到确认分组后可以发送下一个数据分组,‍‍如此反复进行:

  • TD是发送方发送数据分组所耗费的发送时延
  • RTT是收发双方之间的往返时间
  • TA是接收方发送确认分组‍‍所耗费的发送时延

途中忽略了接收方对数据分组的处理时延,‍‍以及发送方对确认分组的处理时延,‍‍因此信道的利用U可以用下式来计算
在这里插入图片描述
TA一般都远小于TD,可以忽略,当RTT远大于TD时,信道利用率会非常低。‍‍

我们来举例说明,‍‍假设信道长度为2000公里,数据分组长度为1500字节,发送速率为10兆比特每秒,‍‍忽略TA,因为TA一般都远小于TD,可以计算出信道利用率约为5.66%,‍‍这是数据分组的发送时延TD,这是往返时间RTT。
在这里插入图片描述
如果将发送速率提高到100兆比特每秒,‍‍则可计算出信道利用率仅为0.6%。这是数据分组的发送时延TD,‍‍这是往返时间RTT
在这里插入图片描述
可以看出当往返时延rtt远大于数据帧发送时延TD时,‍‍例如使用卫星链路,‍‍信道利用率非常低,若出现重传,则对于传送有用的数据信息来说,信道利用率还要降低。‍‍为了克服停止等待协议信道利用率很低的缺点,就产生了另外两种协议‍‍及后退N帧协议GBN,和选择重传协议SRr。‍‍

我们来看一道题
在这里插入图片描述

小结:
像停止等待协议这种通过确认和重传机制实现的可靠传输协议,‍‍常称为自动请求重传协议ARQ,意思是重传的请求是自动进行的,因为不需要接收方显示的请求,发送方重传某个出错的分组
在这里插入图片描述

实现机制 — 回退N帧协议

前面我们介绍了停止等待协议,‍‍如图所示,发送方每发送完一个数据分组,就要停止发送,并等待接收方的确认分组。‍‍当收到接收方的确认分组后,才能发送下一个数据分组,如此反复进行。

从图中可以看出,‍‍每发送完一个数据分组,至少要等待一个收发双方之间的往返时间。‍‍当往返时间较大时,‍‍例如卫星链路‍‍,停止等待协议的信道利用率很低,若出现超时重传,则信道利用率更低。
在这里插入图片描述
如图所示,‍‍如果发送方在收到接收方的确认分组之前,可以连续发送多个数据分组,‍‍则可大大提高信道利用率。这是一种流水线式的传说。‍‍就本例而言,同等条件下,‍‍在相同的时间内,使用停止等待协议的发送方,只能发送一个数据分组,而采用流水线传输的发送方‍‍可以发送5个数据分组。
在这里插入图片描述

接下来我们介绍回退N帧协议,该协议在流水线传输的基础上,利用发送窗口,来限制发送方‍‍可连续发送分组的个数

我们来举例说明,假设采用三个比特给分组编序号,因此‍‍序号的取值范围是0~7,如图所示,这是收发双方各自的分组序号,‍‍当序号增加到7,下一个序号又从0开始,发送方要维持一个发送窗口,‍‍序号落在发送窗口内的数据分组,‍‍可被连续发送,而不必等收到接收方的相应确认分组后再发送。‍‍发送窗口的尺寸即为WT。‍‍对于本例其取值范围是大于1,小于等于23-1,其中的3‍‍是构成分组序号的比特数量,本例取wt的值为5,如果WT的值取为一,则是停止等待协议。‍‍如果WT的值超过取值范围的上限,则会造成严重的错误,我们之后会举例详细说明。

如图所示序号落在发送窗口内的这5个数据分组,可以连续发送,而序号落在发送窗口外的数据分组,‍‍不允许发送。
在这里插入图片描述
接收窗口的尺寸即为WR。对于回退n帧协议,其取值只能为一,‍‍这一点与停止等待协议是相同的。如图所示序号落在接收窗口内的数据分组,允许接收,‍‍而序号落在接收窗口外的数据分组不允许接收。‍‍

我们首先来看最简单的情况,也就是无差错的情况:

  • 发送方将序号落在发送窗口内的0~4号数据分组,依次连续发送出去
  • 他们经过互联网的传输,‍‍正确到达了接收方,也就是没有出现乱序和误码
  • 接收方按序接收他们。每接收一个‍‍接收窗口就向前滑动一个位置,并给发送方发送帧对所接收分组的确认分组
  • 0~4号确认分组,‍‍经过互联网的传输,正确到达了发送方,每接收一个发送窗口就向前滑动一个位置,‍‍这样就有新的序号落入了发送窗口,发送方可以将收到确认的数据分组,‍‍从缓存中删除了
  • 而接收方可以择机将已接收的数据分组交付上层处理。‍‍

在这里插入图片描述

‍接下来‍‍我们来看累积确认的概念,使用回退N帧协议的接收方可以采用累积确认的方式,也就是说‍‍接收方不一定要对收到的数据分组逐个发送确认,而是可以在收到几个数据分组后,‍‍对按序到达的最后一个数据分组发送确认,ackn表示序号为n及以前的所有数据分组‍‍都已正确接收了

我们来举例说明累计确认‍‍。发送方将序号落在发送窗口内的0 ~ 4号数据分组,依次连续发送出去,他们经过互联网的传输,‍‍正确到达了接收方按序接收他们。当接收完0号和1号数据分组后,‍‍给发送方发送了一个累积确认ack1,当接收完2~4号数据分组后,‍‍又给发送方发送了一个累计确认ack4,假设ack1在传输过程中丢失了,‍‍而ack4正确到达了发送方,发送方接收ack4后就知道了,‍‍序号为4及之前的数据分组已被接收方正确接收了,于是将发送窗口向前滑动5个位置,‍‍这样就有新的序号落入了发送窗口,‍‍发送方可以将收到确认的数据分组从缓存中删除了,而接收方可以择机将已接收的数据分组‍‍交付上层处理。‍‍
在这里插入图片描述
从本例可以看出,使用累计确认的其中一个优点,就是即使确认分组丢失,‍‍发送方也可能不必重传。例如本例ack1丢失了,‍‍但并没有造成一号数据分组的超时重传

使用累计确认还有其他好处。比如‍‍可以减小接收方的开销,减少对网络资源的占用等。‍‍当然了‍‍使用累计确认也有缺点,那就是不能向发送方及时反映出‍‍接收方已经正确接收的、数据分组的信息。‍‍

接下来我们来看出现差错的情况,‍‍发送方将序号落在发送窗口内的这5个数据分组,依次连续发送出去,‍‍他们经过互联网的传输到达了接收方,假设他们在传输过程中受到了干扰,‍‍其中5号数据分组出现了误码,接收方通过数据分组中的检错码发现了错误,‍‍于是丢弃该数据分组。而后续到达的这4个数据分组的序号与接收窗口中的序号不匹配,‍‍接收方同样也不能接受他们,‍‍将他们丢弃并对之前按序接收的最后一个数据分组进行确认,也就是发送ack4,‍‍每丢弃一个数据分组,就发送一个ack4,这4个ack4经过互联网的传输到达了接收方,‍‍发送方之前就接收过ack4,当收到这些重复的ack4时,‍‍就知道了之前所发送的数据分组出现了差错,于是可以不等超时计时器超时‍‍就立刻开始重传。‍‍
在这里插入图片描述

至于收到几个重复确认,就立刻重传,由具体实现来决定。‍‍在本例中,假设收到这4个重复的确认,并不会触发发送方立刻重传。一段时间后,‍‍超时计时器出现超时,发送方将发送窗口内已发送过的这些数据分组全部重传。‍‍在本例中,尽管序号为6701的数据分组,之前已经正确的到达接收方,‍‍但由于5号数据分组误码不被接受,他们也受到牵连而不被接受。‍‍
在这里插入图片描述

发送方还要重传这些数据分组,‍‍这就是所谓的go back-n也就是回退n帧。‍‍可见当通信线路质量不好时,‍‍回推N帧协议的信道利用率并不比停止等待协议高

接下来我们来看看,如果发送窗口的尺寸,WT超过其取值范围的上限会出现什么情况?

对于本例,采用三个比特给分组编序号,‍‍wt的最大值为2的三次-1,也就是7,我们故意超过该上限将WT取值为8,‍‍发送方将序号落在发送窗口内的0~7号这8个数据分组依次连续发送出去,‍‍他们经过互联网的传输,正确到达了接收方,接收方按序正确接收他们号,‍‍给发送方发回累计确认ack7。‍‍

假设ack7在传输过程中丢失了,‍‍这将导致发送方的超时重传重传的0~7号数据分组到达接收方。现在问题来了,‍‍接收方根据当前接收窗口内的序号,会对这8个数据分组按序接收,但是‍‍接收方之前已经接收过这8个数据分组了,现在是在重复接收,也就是说‍‍接收方无法分辨新旧分组,进而会产生分组重复这种传输差错,因此‍‍发送窗口的尺寸不能超过其上限。
在这里插入图片描述

接下来我们对回退n帧协议的工作原理进行一下小结:
在这里插入图片描述

然后我们来看一道题:
在这里插入图片描述

回退N帧协议在流水线传输的基础上,‍‍利用发送窗口来限制发送方连续发送数据分组的数量,是一种连续ARQ协议‍‍。在协议的工作过程中,发送窗口和接收窗口不断向前滑动,因此‍‍这类协议要称为滑动窗口协议。‍‍由于回退n帧协议的特性,当通信线路质量不好时,‍‍其信道利用率并不比停止等待协议高。

实现机制 — 选择重传协议

前面我们介绍了回退n帧协议,‍‍回退n帧协议的接收窗口尺寸WR只能等于1,因此‍‍接收方只能按序接收正确到达的数据分组,一个数据分组的误码,就会导致其后续多个数据分组不能被接收方按序接收而丢弃,尽管他们没有误码,这必然会造成发送方‍‍对这些数据分组的超时重传,显然这是对通信资源的极大浪费。‍‍

为了进一步提高性能,‍‍可设法只重传出现误码的数据分组。因此接收窗口的尺寸w不应再等于一,‍‍而应大于1,以便接收方先收下失序到达,但无误码,并且序号落在接受窗口内的那些数据分组,等到所缺分组收齐后,再一并送交上层。‍‍这就是要介绍的选择重传协议。‍‍

需要注意的是选择重传协议,为了使发送方‍‍仅重传出现差错的数据分组,接收方不能再采用累积确认,而需要对每个正确接收到的数据分组‍‍进行逐一确认

下面我们来举例说明,选择重传协议的工作原理。假设采用三个比特‍‍给分组编序号,因此序号的取值范围是0~7,如图所示:

在这里插入图片描述
当序号增加到7时,下一个序号又从0开始,‍‍发送窗口的尺寸,wt的取值范围是大于1,小于等于2的3次方-1次。其中的三‍‍是构成分组序号的比特数量,本例取wt的值为4,如图所示‍‍序号落在发送窗口内的这4个数据分组可以连续发送,‍‍而序号落在发送窗口外的数据分组不允许发送。
在这里插入图片描述
接收窗口的尺寸WR的取值,一般情况下‍‍可以发送窗口的尺寸WT的取值相同,在本例中其值为4,如图所示‍‍序号落在接收窗口内的这4个数据分组允许接收,而序号落在接收窗口外的数据分组不允许接收
在这里插入图片描述

过程如下:

  • 发送方将序号落在发送窗口内的这4个数据分组,依次连续发送出去,‍‍他们经过互联网的传输陆续到达接收方,但其中的2号数据分组丢失了,‍‍只要序号落入接收窗口内,且无误码的数据分组,接收方都会接收。接收方接收0号‍‍和1号数据分组,并发送0号和1号确认分组,接收窗口向前滑动两个位置,这样‍‍就有4和5这两个新的序号落入接收窗口,接收方接收3号数据分组,并发送3号确认分组,‍‍但接收窗口不能向前滑动,因为3号数据分组是未按需到达的数据分组,‍‍这些确认分组经过互联网的传输,陆续到达发送方,每按序收到1个确认分组,‍‍发送窗口就向前滑动1个位置
    在这里插入图片描述
  • 发送方接收0号和1号确认分组,‍‍发送窗口向前滑动两个位置,这样就有4和5这两个新的序号落入发送窗口,‍‍发送方将序号落入发送窗口的4号和5号数据分组发送出去,‍‍发送方现在可以将已经收到确认的0号和1号数据分组从发送缓存中删除了,‍‍而接收方可择机将以按需接收的0号和1号数据分组交付上层处理
    在这里插入图片描述
  • 发送方接收三号确认分组,但发送窗口不能向前滑动,因为这是一个未按需到达的确认分组,‍‍发送方还未收到他之前的2号确认分组,不过需要记录3号数据分组已收到确认,‍‍这样该数据分组就不会超时重发。‍‍4号和5号数据分组到达接收方,接受方接受他们,‍‍并发送4号和5号确认分组,但接收窗口不能向前滑动,因为他们是未按需到达的数据分组,‍‍接收方还未收到他们之前的2号数据分组。‍‍
    在这里插入图片描述
  • 假设在4号和5号确认分组的传输过程中,‍‍发送方帧对2号数据分组的重传计时器超时了,发送方重传23号数据分组,‍‍4号和5号确认分组陆续到达发送方,发送方接收他们,但发送窗口不能向前滑动,‍‍因为他们是未按时到达的确认分组,发送方还未收到他们之前的2号确认分组,不过‍‍需要记录4号和5号数据分组已收到确认,这样他们就不会超时重发。‍‍
    在这里插入图片描述
  • 发送方之前重传的二号数据分组到达接收方,接收方接收该数据分组,并发送2号确认分组,‍‍接受窗口现在可以向前滑动4个位置,这样就有6‍‍701这4个新的序号落入接收窗口。‍‍
    在这里插入图片描述
  • 2号确认分组,经过互联网的传输,到达发送方,发送方接收该确认分组,‍‍发送窗口现在可以向前滑动4个位置,这样就有6701‍‍这4个新的序号落入发送窗口,发送方现在就可以继续将这4个序号的数据分组‍‍依次发送出去了。‍‍
    在这里插入图片描述

接下来我们再来讨论一下,选择重传协议的发送窗口和接收窗口的尺寸问题。‍‍发送方的发送窗口尺寸wt必须满足大于1小于等于2的n减一次,其中n‍‍是构成分组序号的比特数量。若wt等于1则与停止等待协议相同,‍‍若wt>2的n减一次,则会造成接收方无法分辨新旧数据分组的问题。‍‍

接收方的接收窗口尺寸,WR必须满足大于一,‍‍小于等于wt。若WR等于1则与回退n帧协议相同,若WR大于wt,‍‍则没有意义。

‍下面我们就来看看,如果发送窗口和接收窗口的尺寸超过了他们的取值范围,‍‍会出现什么样的情况?‍‍我们还是采用三个比特给分组编序号,即序号0~7,‍‍发送窗口的尺寸,wt取最大值,接收窗口的尺寸WR也取最大值,‍‍也就是wt等于WR‍‍=2的3-1次=4。假设我们故意将发送窗口尺寸WT设置为5,相应的‍‍将接收窗口尺寸wr也设置为5,看看会出现什么情况。‍‍

  • 发送方将序号落入发送窗口内的0~ 4号这5个数据分组依次发送出去,‍‍他们经过互联网的传输,依次到达接收方,接收方接收他们,并发送0~4号确认分组,‍‍接收窗口向前滑动5个位置,这样就有5‍‍6701这5个新的序号落入接收窗口
    在这里插入图片描述
  • 这些确认分组经过互联网的传输,陆续到达发送方,但其中的0号确认分组丢失了,‍‍发送方接收1~4号确认分组,并记录1 ~ 4号数据分组已收到确认,发送窗口不能向前移动。‍‍
    在这里插入图片描述
  • 一段时间后,0号数据分组的重传计时器超时了,发送方重传0号数据分组,‍‍该数据分组经过互联网的传输到达接收方,‍‍其序号0落在接收窗口内,接收方会接收它,但是‍‍接收方先前已经正确接收过该数据分组了,如果现在还要接收,‍‍那就会出现分组重复这种传输差错。也就是说如果发送窗口和接收窗口的尺寸‍‍超过了取值范围,就会使接收方无法分辨新旧数据分组,‍‍进而出现分组重复这种传输差错。
    在这里插入图片描述

我们来练习一个题;
在这里插入图片描述

接下来我们对选择重传协议的工作原理进行一下小结:
在这里插入图片描述

点对点协议PPP

点对点协议,PPP是目前使用最广泛的点对点数据链路层协议。
在这里插入图片描述

请大家想想看,‍‍一般的因特网用户是如何接入到因特网的,通常都是要通过连接到某个因特网服务提供者ISP,‍‍例如中国电信、中国联通、中国移动这三大运营商才能接入因特网。‍‍这些ISP‍‍已经从因特网管理机构申请到了一批IP地址,用户计算机只有获取到ISP所分配的合法IP地址后,‍‍才能成为因特网上的主机。
用户计算机与ISP进行通信时所使用的数据链路层协议,‍‍通常就是PPP协议。这里需要说明的是在1999年公布的在以太网上运行的PPP协议,‍‍即PPP over ethernet,简称为pppoe。它使得ISP可以通过DSL电路调制解调器、‍‍以太网等宽带接入技术,以以太网接口的形式‍‍为用户提供接入服务。‍‍另外点对点协议PPP也广泛应用于广域网路由器之间的专用线路。‍‍

PPP协议是因特网工程任务组IEFT在1992年制定的,经过1993年‍‍和1994年的修订,现在的PPP协议已成为因特网的正式标准。‍‍我们可以在IEFT官方网站的相关页面,搜索并查看PPP协议的相关rfc文档

PPP协议为在点对点链路传输各种协议数据报提供了一个标准方法,‍‍主要由以下三部分构成。‍‍

  • 对各种协议数据报的封装方法,‍‍也就是我们之前课程中介绍的封装成帧。
  • 链路控制协议lcp,用于建立配置‍‍以及测试数据链路的连接。
  • 一套网络控制协议ncps,其中的每一个协议‍‍支持不同的网络层协议

在这里插入图片描述

从网络体系结构的角度看:

  • PPP是数据链路层的协议,‍‍他将上层交付下来的协议数据单元‍‍封装成PPP帧.

  • 为了支持不同的网络层协议,PPP协议包含了一套网络控制协议ncp‍‍s,其中的每一个协议支持不同的网络层协议,例如tcpip中的IP‍‍ novell neteware,网络操作系统中的IPX,苹果公司的apple talk等。

  • 链路控制协议LCP,用于建立配置以及测试数据链路的连接,PPP协议能够在多种类型的点对点链路上运行,‍‍例如面向字节的异步联络,‍‍面向比特的同步链路。‍‍

接下来我们来看看PPP协议的帧格式,帧首部由4个字段构成,‍‍帧尾部由两个字段构成,各字段的长度以及帧的数据部分的最大长度如图所示‍‍:
在这里插入图片描述

我们来看看PPP协议是如何解决透明传输问题的。‍‍当PPP帧的数据部分‍‍出现帧手和帧尾中的标志字段时,如果不采取措施,‍‍则会造成接收方对PPP帧是否结束的误判。因为标志字段是PPP帧的定界,符‍‍取值为16进制的7E,也就是二进制的0111 1110。

PPP协议实现透明传输的方法,‍‍取决于所使用的链路类型。‍:

  • 如果是面向字节的异步电路,则采用字节填充法,也就是插入转义字符。‍‍

  • 如果是面向比特的同步电路,则采用比特填充法,也就是插入比特0。‍‍

我们来举例说明字节填充法,也就是以字节7E,作为PPP帧的定制符,‍‍以字节为单位来讨论问题:

在这里插入图片描述

我们再来举例说明比特填充法也就是以0111 1110作为PPP帧的定界符,‍‍以比特为单位来讨论问题:
在这里插入图片描述


接下来‍‍我们来看看PPP协议‍‍是如何进行差错检测的

PPP帧的尾部包含有一个两字节的帧检验序列fcs字段,‍‍使用循环冗余校验crc来计算该字段的取值。采用的生成多项式如下所示。‍‍Rfc1662文档的附录部分,给出了fcs的计算方法的c语言实现。‍‍为了减少对CPU的占用,采用查表法来实现fcs的计算范围,如图所示

接收方每收到一个PPP帧就进行crc检验,若crc检验正确,就收下这个帧,‍‍反之就要丢弃这个帧,‍‍使用PPP的数据链路层,向上不提供可靠传输服务。
在这里插入图片描述


最后我们以拨号接入为例,‍‍简单介绍一下PPP协议的工作状态:
在这里插入图片描述

  • PPP链路的开始和结束状态都是静止状态,‍‍这时并不存在物理层的连接。

  • 当检测到调制解调器的载波信号,并建立物理层连接后,‍‍PPP就进入链路的建立状态。‍‍

  • 这时链路控制协议lcp开始协商一些配置选项,‍‍若协商成功‍‍则进入鉴别状态,若协商失败则退回到静止状态。

  • 所协商的配置选项,‍‍包括最大帧长,鉴别协议等,可以不使用鉴别,也可以使用口令鉴别协议pap‍‍或挑战握手鉴别协议chap

  • 若通信双方无需鉴别或鉴别身份成功,‍‍则进入网络状态,若鉴别失败则进入终止状态,

  • 进入网络状态后,进行ncp配置,‍‍配置完成后就要进入打开状态。

  • PPP链路的两端,通过相互交换网络层特定的ncp分组‍‍来进行ncp配置。‍‍如果在PPP链路上运行的是IP协议,则使用IP控制协议ipcp‍‍来对PPP链路的每一端配置IP模块,例如分配IP地址

  • 只要链路处于打开状态,‍‍就可以进行数据通信。当出现故障或链路的一端发出终止请求时,就进入终止状态。‍‍

  • 当载波停止后‍‍则回到静止状态


内容小结如下:
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/121949.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!