zoukankan      html  css  js  c++  java
  • 数据链路层

    数据链路层的设计问题

    数据链路层完成的功能:1.向网络层提供一个定义良好的服务接口;2.处理传输错误;3.调节数据流,确保慢速的接收方不会被快速的发送方淹没。

    提供给网络层的服务

    1. 无确认的无连接服务:是指源机器目标机器发送独立的帧,目标机器并不对这些帧进行确认。对于这种服务,实现不需要建立逻辑连接,事后也不需要释放逻辑连接。若由于线路的噪声而造成某一帧的丢失,数据链路层并不会试图检测和恢复丢失的帧。
    2. 有确认的无连接服务:在这种服务中,数据链路层仍然没有使用逻 辑连接,但其发送的每一帧都需要单独确认
    3. 有确认的有连接服务:在这种服务中,源机器和目标机器在传输任何数据前要建立一个连接。连接上发送的每一帧都被编号,数据链路层确保发出的每个帧都会真正被接收方收到。它还保证每个帧只被接收一次,并且所有帧都将按正确的顺序被接收。

    成帧1.字节计数法:利用头部中的一个字段来标识该帧中的字符数。当接收方的数据链路层看到字符计数值时,它就知道后面跟着多少个字节,因此也就知道了该帧在哪里结束。

                                       这个算法的问题在于计数值有可能因为一个传输错误而被弄混。

             2.字节填充的标志字节法:这种方法考虑到出错后的重新同步问题,它让每个帧用一些特殊的字节作为开始和结束。这些特殊字节通常相同,称为标志字节(FLAG),发送方的 数据链路层在数据中“偶尔”出现的每个标志字节前面插入一个特殊的转义字节(ESC)。因此,只要看到它数据中出现的标志字节的前面有没有转义字节,就可以把它作为帧分界符的标志字节与数据中出现的标志字节区分开来。接收方的数据链路层在将数据传递给网络层前必须删除转义字节。

            3.比特填充的标志比特法:在这种方法中,每个帧的开始和结束由一个特俗的比特模式,01111110或十六进制0x7E标记。这种模式是一个标志字节。每当发送方的数据链路层在数据中遇到连续的五个1,它便自动在输出的比特流中填入一个比特0.当接收方看到5个连续入境的比特1,并且后面紧跟一个比特0,它就自动剔除比特0。

            4.物理层编码违禁法:这种方法是一条使用物理层的捷径。有些比特编码成信号的方案中会有一些冗余比特,可以用于帮助接收器同步接收。这种冗余意味着一些信号将不会出现在常规数据中。比如4B/5B线性编码模式中,4个数据位被映射成5个信号比特,这意味着32个可能信号中有16个是不会被使用的,我们可以用这些保留的信号来指示帧的开始和结束。

    差错控制:数据链路层的误差控制是基于自动重复请求,即数据重传。

    流量控制:发送方需要调节数据流,确保慢速的接收方的数据不会被淹没。流量控制通常有两种方法,第一种是基于反馈的流量控制,接收方给发送方返回信息,允许它发送更多的 数据,或者至少告诉发送方自己的情况怎么样。第二种方法是基于速率的流量控制,使用这种方法的协议有一种内置的机制,它能限制发送方传输数据的速率,而无需利用接收方的反馈信息。

    检错与纠正

    数据错误:一种是单比特错误,即只有一位发生了变化;另一种是突发型错误,是指发生两位或两位以上的错误。

    海明距离:两个码字间的不同位的个数。

    最小海明距离:在一种编码方案中,最小的那个海明距离。为了检测出d个错误,需要最小海明距离为d+1的编码方案;为了纠正d个错误,需要最小海明距离为2d+1的编码方案。

    校验位和数据位的关系:设一个码字有n位,其中有m位数据位,r位校验位。任何一个消息都有n种单比特错误,即逐位取反。那么就需要n+1个位模式来标记它们。而一共有2^m个合法消息,所以有(n+1)*2^m<=2^n。而n=m+r,所以(m+r+1)<=2^r

    海明码:在海明码中,码字的位被连续的编号,从左到右一次编号为1,2,3……,2的幂次方位是校验位,其余的为数据位。若要查看数据k位上的校验位,必须将k改写成2的幂之和。

                  校验过程:设有5位,依次标号为p1,p2,m3,p4,m5。p代表校验位,m代表数据位。对校验位从高位到低位,进行校验:p4⊕m5=x1 p2⊕m3=x2 p1⊕m5⊕m3=x3。那么x1x2x3组合成的二进制数,所对应的十进制数代表第几号位出错。如果x1、x2、x3全为零则代表没有错误。

    奇偶校验码:把单个奇偶校验位附加到数据中。奇偶位的选择原则是使得码字中的比特数目是偶数(或者奇数)。具有单个校验位的编码具有码距2,因为任何一位错误都将使得码字的奇偶校验码出错。这意味着奇偶码可以检测出1位错误。

                          通常,将要发送的信息块分为定长p位的q段,即高为q,宽为p。

                          垂直奇偶校验码:校验每段的某一位,放在信息块的最下端。这种编码方案的编码效率为q/(q+1)

                         水平奇偶校验码:校验某一段的每位,放在信息块的最右端。这种编码方案的编码效率为p/(p+1)

                         水平垂直奇偶校验码:是水平奇偶校验码和垂直奇偶校验码的结合方案,这种编码方案的编码效率为p*q/[(p+1)*(q+1)]

    校验和:1的补码和:即将参与运算的数取反码,再进行一般二进制加法相加,最终最高位的进位要加在最低位上。

                  发送方:第一步,将发送的进行检验和运算的数据分成若干个16位的位串,每个位串看成一个二进制数;第二步,将校验和字段置为0,该字段也参与检验和运算;第三步,对这些16位的二进制数进行1的补码和运算,累加的结果再取反码就生成了校验码。将校验码放入校验和字段中。

                  接收方:第一步,接收方将接收的数据包括校验和字段按同样的方式进行1的补码和运算,累加的结果再取反码;第二步,检验,如果最终结果为0,则为有效帧,否则就是无效帧。

    循环冗余码:(CRC),算法步骤:1)假设G(x)的阶为r(最高的次数)。在帧的低位段加上r个0位,使得该帧现在包含m+r位,对应多项式为x^r * M(x)。2)利用模二除法,用对应于G(x)的 位串去除对应于x^r * M(x)的位串。3)利用模二减法,从对应于x^r * M(x)的位串中减去余数(总是小于等于r位)。结果发出的帧就是附加上r个0的帧再加上余数。

                        如果错误发生再G(x)中,则错误无法被检测出;如果G(x)包含两项或更多的项,则可以检测出所有的一位错误;而能够检测出两位错误的充分条件是:对于任何小于等于 i-j最大值(即小于等于最大帧长)的k值,G(x)都不能除尽x ^k+1;如果x+1作为G(x)的因子,就可以检测出所有包含奇数个位的错误。

                        带r个校验位的多项式编码可以检测到所有长度小于等于r的突发错误;如果一个帧突发错误的长度等于r+1,那么这样一个不正确的帧被作为有效帧被接收的概率为      1/2(r-1);如果一个帧突发错误的长度大于r+1,或者几个短突发错误发生时,一个坏帧被当作有效帧接收的概率为1/2^r。

    基本数据链路层协议

    帧:一个帧由4个字段组成:kind、seq、ack、和info,其中前三个包含控制信息,最后一个可能包含了要被传输的实际数据。这些控制字段合起来被称为帧头。

           其中kind字段指出了帧是否有数据,因为有些协议需要区分只含有控制信息的帧和同时包含控制信息和数据的帧;而seq和ack分别用作序号和确认。数据帧的info字段包含一个数据包,控制帧的info字段没有用处。

    乌托邦式的单工协议:没有考虑流量控制与差错控制,只是简单的发送与接收。

    无错信道上的单工停-等协议:解决流量控制:一种方法是建立足够强大的接收器,使其强大到能处理一个接着一个帧组成的连续流。而一般化的解决方案是,让接收方给发送方提供反馈信息。接收方将数据包传递给网络层之后给发送方返回一个哑帧来允许它发送下一个帧。

    有错信道上的单工停-等协议:解决差错控制:对于发送方,增加一个计时器,如果一定时间内没有接收到确认帧,则重传之前发送的数据帧,直到收到确认帧为止;而对于接收方, 需要对每一帧的序号进行确认,从而避免向网络层提交重复的帧。

    滑动窗口协议

    滑动窗口:发送窗口内的序号代表了那些可以被发送的帧,或者那些已经被发送但还没有接收到确认帧的帧。任何时候当有新的数据包从网络层到来时,它被赋予窗口中的下一个最高序号,并且窗口的上边界前移一格。当接收到一个确认帧时,窗口的下边界也前移一格。

                      当发送窗口达到最大值时,发送方的数据链路层必须强行关闭网络层,直到一个缓冲区空闲出来为止。

                      接收方数据链路层的窗口对应于它可以接收的帧。任何落在窗口内的帧都将被放入接收方的缓冲区。当接收一个帧,而且其序号对应于窗口的下边界时,接收方将其传递给网络层,并将整个窗口向前移动1个位置。任何落在窗口外的帧都将被丢弃。

    一位滑动窗口协议:捎带应答:当双方都要传递数据时,将确认序号携带在数据帧中可以减少开销。

                                                      这样一来,接收方就需要确认两样数据,一是帧的序号,避免上传重复帧。二是帧的确认序号,对上一个正确发送的帧确认信息。

    • 在正常情况下,发送方和接收方是交替发送的;但如果最开始发送方和接收方同时发送,或者超时设置得太短时,会造成不必要的重发,但协议依然能正常运行。

                                    发送流程:1)初始化:next_frame_to_send=0; frame_expected=0; 前一项数据表示,发送方正在发送的帧的序号,后一项数据表示接收方期待接收的帧的序号。

                                                      2)构造一个帧:序号seq=next_frame_to_send;确认信息ack=1-frame_expected。将从网络层接收到的数据包装入info字段。

                                                      3)将帧传递给物理层,同时启动计时器。

                                   接收流程:首先检查seq字段,若接收帧的序号正是期待接收的帧的序号(seq==frame_expected),则将帧的info字段提交至网络层,并将frame_expected反转;然后检查ack字段,若正式等待的确认帧(ack=next_frame_to_send),则关闭相关计时器,从网络层接收一个新的分组放入缓冲区,并将next_frame_to_send反转。

    管道化:为了提高信道利用率,人们希望能够在等待确认帧的时候多发送一些帧。这事实上允许发送窗口包含多个未确认的帧,这种技术称为管道化。当信道传播延迟远大于帧的传 输延迟,适合采用这种技术。

                  但这样会面临一个问题:位于帧流中的某个帧丢失或损坏了,另外在发送进程发现错误前,大量的后继帧会到达接收方。

    回退N协议:接收进程会丢弃所有的后继帧,并且不通知发送进程。该策略对应接收窗口为1的情况,即只能按顺序接收帧,当发送进程超时后,必须按顺序重传所有未被确认的帧。

                        如果出错率高的话,这种方法会浪费很多带宽,但对内存要求不高。

                        工作流程:1)初始化:打开网络层允许; ack_expected=0,这个数据表示最早未被确认的帧; next_frame_to_send=0, frame_expected=0; nbuffered=0,这个数据表示发送窗口的大小。

                                          2)等待事件发生(网络层准备好、帧到达、收到坏帧、超时)

                                          3)如果事件为网络层准备好,则冲网络层接收一个分组,放入相应的缓冲区;发送窗口大小加1;构造一个帧:seq=next_frame_to_send;  ack=(frame_expected+MAX_SEQ)%(MAX_SEQ+1); 发送至物理层,启动计时器。

                                          4)如果事件为帧到达,则从物理层接收一个帧。首先检查帧的seq字段,若正是期待的帧(seq==frame_expected), 则将其发送至网络层,frame_expected+1;然后检查帧的ack字段,若ack落在发送窗口内,则表示该序号及其之前的帧均已确认到达,因此终止这些帧的计时器,修改发送窗口的大小及其下沿值,将位于缓冲区的这些帧都去掉。

                                          5)如果事件为收到坏帧,则忽略(什么也不做)。

                                          6)如果事件为超时,即:next_frame_to_send=ack_expected,从发生超时的帧开始重发发送窗口内的帧,

                                          7)若发送窗口大小小于所允许的最大值(MAX_SEQ),则可继续向网络层发送,否则则暂停继续向网络层发送,同时返回步骤2。

                       在这个协议中有一个问题,没有考虑当某个方向上没有数据要发送时,要对收到的帧进行单独确认。在收到期待的帧后应该启动一个ACK计时器,当超时事件发生时,应 确认是哪个计时器发生超时,若是ACK计时器超时,应该单独发送一个确认帧。而当发送了一个数据包时,应将被捎带确认的帧的ACK计时器终止。

    选择重传协议:只要是落入接收窗口并且校验正确的帧,都要接收下来放到缓存区内。这样当意识到某个帧出错时,只是重传此帧而非所有的后续帧。

                            选择重传通常采用NAK对校验出错或疑似丢失的帧进行确认,以便发送进程尽快重传该帧。如果第二次重传成功,接收方的数据链路层中会有许多按顺序排列的正确                           帧,这些帧可以一起交给网络层,并且只对最高序号的帧进行确认。

                           当发送窗口很大时,这种方法需要大量的内存,当它并不浪费带宽。

                           工作流程1)初始化:类似GO-BACK-N的初始化,但增加了与接收窗口相关的内容,如设定接收窗口的大小、清空缓冲区满标志等。

                                             2)等待事件发生(帧到达,收到坏帧,数据帧超时,网络层准备好,ACK超时)。

                                             3)如果发生的事件为网络层准备好,则从网络层接收一个分组,组帧发送,修改相关参数,与GO-BACK-N的处理方法相同,继续执行步骤(6)。

                                             4)如果事件为帧到达,则从物理层接收一个帧,

    • 若为数据帧,且不是期待接收、未发送过NAK(不应答)的帧,则发送一个NAK帧,要求重发指定序号的帧(Frame_expected);否则启动ACK计时器;若收到的帧落在接收窗口内,且此前未收到过,则放入相应缓冲区并设置缓冲区满标志;若接收窗口下沿帧已经到达,则从该帧开始将连续的若干个帧交给网络层,并修改相应参数(缓冲区满标志,接收窗口范围),启动ACK计时器。
    • 若为NAK帧,且请求重发的帧落在当前的发送窗口内,则重发这个帧。若从发送窗口下沿开始连续的若干个帧已被确认,则终止这些帧的计时器,修改发送窗口大小及发送窗口下沿值将这些帧去掉;继续执行下一步。

                                            5)如果发生的事件为收到坏帧,则在尚未发送过NAK时,发送一个NAK,继续执行步骤(6);如果发生的事件为超时(数据帧超时),重发超时的帧,也继续执行步骤(6);如果事件为ACK超时,为指定的帧发送单独的确认帧,同样继续执行步骤(6)

                                            6)若发送窗口大小小于所允许的最大值(NR_BUFS),则允许继续向网络层发送帧,否则暂停向网络层继续发送帧,返回到步骤2,继续等待。

  • 相关阅读:
    【Node.js 自己封装的库 http_parse, libuv】
    select遍历list默认选中初始值
    mybatis入门基础----高级映射(一对一,一对多,多对多)
    工具类 | window批处理杀死指定端口进程
    eclipse 关闭控制台 自动弹出
    mybatis的jdbcType和javaType、oracle,MySQL的对应类型
    mysql 创建表格 AUTO_INCREMENT
    Linux shell脚本启动 停止 重启jar包
    Tomcat结合nginx使用小结
    集成maven和Spring boot的profile功能
  • 原文地址:https://www.cnblogs.com/TheFutureIsNow/p/10767075.html
Copyright © 2011-2022 走看看