计算机网络原理总结(英文版 第五版) Chapter3

数据链路层

 

在本章中,我们将学习网络模型中的第二层(即数据链路层)的设计原则。学习内容涉及两台相邻机器实现可靠有效的完整信息块(称为帧)通信的一些算法

3.1 数据链路层的设计问题

 

数据链路层要完成一些功能,包括:

(1)向网络层提供一个定义良好的服务接口

(2)处理传输错误

(3)调节数据流,确保慢速的接收方不会被快速的发送方淹没

为了实现这些目标,数据链路层接受来自网络层的数据包,并将它们封装成帧以便传输。每个帧包含一个帧头、一个有效荷载(用于存放数据包)以及一个帧尾,如下图所示。帧的管理构成了数据链路层工作的核心

 

物理层所做的是接受原始比特流并将其传递到目的地。

但是如果信道是有噪声的,则数据链路层接收的比特流不能保证是无差错的。

 

3.1.2 成帧

 

为了向网络层提供服务,数据链路层必须使用物理层提供给它的服务。物理层所做的只是接受一个原始比特流,并试图传给他的目标机器。然而,数据链路层接收到的比特流不能保证没有错误。检测错误和纠正错误(有必要的话)的工作正是数据链路层该做的

 

对数据链路层来说,通常的做法是将比特流分解成多个离散帧,为每一个帧计算一个称为校验和短令牌,并将该校验和放在帧中一起传输。当帧到达目标及其实,要重新计算该帧的校验和。

 

拆分比特流的实际工作比初看上去的要复杂得多。一个好的设计方案必须使接收方很容易发现一个新帧的开始,同时了解所使用的信道带宽要多少。我们将考察下面4种方法:。

(1)字节计数

(2)字节填充的标志字节法

(3)比特填充的标志比特法

(4)物理层编码违禁法

 

 

第一种成帧方式利用头部中的一个字段来标识该帧中的字符数。当接收方的数据链路层看到字符计数值时,它就知道后面跟着多少个字节,因此也就知道了该帧在那里结束。如下图所示,其中4帧的大小分别为5、5、8、8个字节。

这种算法的问题在于计数值可能因为一个传输错误而被弄混。每个帧的第一个字符代表了帧的长度。

 

第二种成帧方法考虑到了出错之后的重新同步问题,它让每个帧用一些特殊的字节作为开始和结束。这些特殊字节通常都相同,称为标志字节(flag byte),作为帧的起始和结束分界符。两个连续标志字节代表了一帧的结束和下一帧的开始。因此,如果接收方丢失了同步,他只需要搜索两个标志字节就能找到当前帧的结束和下一帧的开始位置。

但是,当标志字节出现在数据中时,尤其是当传输二进制数据时(比如歌曲、照片),这种情况会严重干扰到帧的分界。解决方法是发送方的数据链路层在数据中“偶尔”出现的每个标志字节的前面插入一个特殊的转义字节(ESC),就可以把作为帧分界符的标志字节与数据中出现的标识字节区分开来。而接收方的数据链路层在将数据传递给网络层之前必须删除转义字节。这种技术就称为字节填充(byte stuffing)

下图介绍了如何解决转义字节也出现在数据中的问题(在转义字节前再加一个转义字节),使用的字节填充方案是PPP协议(Point-to-Point Protocol):

 

 

第三种方法区分比特流边界的方法考虑了字节填充的缺点,即只能使用8比特的字节(因为1字节=8bit)。帧的划分可以在比特级完成,因而帧可以包含任意大小单元(而不是只能以8比特为单元)组成的二进制比特数。这种方法是为曾经非常流行的HDLC(高级数据链路控制)协议而开发的。每个帧的开始和结束由一个特殊的比特模式,01111110或十六进制0x7E标记

每当发送方的数据链路层遇到连续的五个1,它就会自动在输出的比特流中填入一个比特0。当接收器看到5个连续传入的1位,接着是0位时,它自动去掉0位。比特填充确保了转换的最小密度,这将有利于物理层保持同步。正是由于这个原因,USB(通用串行总线)采用了比特填充技术。

最后一种方法是一条使用物理层的捷径的方法。当比特编码成信号时通常会出现一些冗余比特,以便帮助接收器同步接收。这意味着32个可能的信号中有16个是不会被使用的。我们可以利用这些保留的信号来指示帧的开始和结束。实际上,我们使用“编码违法”来区分真的边界。这种方法的优点在于这些用分节符的信号是保留不用的,所以很容易通过它们找到帧的开始和结束,而且不再需要填充数据。

 

3.1.3 差错控制

解决了如何标识每一帧的起始和结束位置之后,我们需要关注:如何确保所有的帧最终都被传递给目标机器的网络层,并且保持正确的顺序对于无确认的无连接服务,不管发出去的帧是否正确抵达目标机器,发送方只要把出境帧留存就可以了但是对于可靠的、面对连接的服务,确保可靠传递的方法是向发送方提供一些有关线路另一端状况的反馈信息。通常情况下,协议要求接收方发回一些特殊的控制帧,在这些控制帧中,对于它所接收到的帧进行肯定的或者否定的确认。如果发送方收到了关于某一帧的肯定确认,那么它就知道这帧已经安全地到达了。另一方面,否定的确认意味着传输过程中出现了错误,所以这个帧必须重传。

如果帧丢失,可以通过启动一个计时器来解决这个问题。

 

3.2 差错检测和纠正

 

网络设计者已经开发出两种处理错误的基本策略。两者都将冗余信息添加到发送的数据中。

前一种策略使用纠错码(error-correcting code)

错误频繁的信道上,例如无线链路。

后一种策略使用检测码(error-detecting code)

通道是高度可靠的,例如光纤。

 

3.2.1 纠错码

我们将考察一下4中不同的纠错编码:

(1)海明码

(2)二进制卷积码

(3)里德所罗门码

(4)低密度奇偶校验码

上述所有编码都将冗余信息加入到待发送的信息中。在块码(block code)中,r个校验位是作为与之相关的m个数据为的函数计算获得的。就像在一张大表中找到m位数据对应的r校验位。在系统码(systematic code)中,直接发送m个数据位,然后发出r个校验位,而不是在他们发送前对它们进行编码。在线性码(line code)中,r个校验位是作为m个数据位的线性函数被计算出来的。

令数据块的总长度为n(n=m+r)。我们将此描述为(n,m)码。一个包含了数据位和校验位的n位单元称为n位码字(code word)码率(code rate)或者简单地说速率,则定义为码字中不包含冗余部分所占的比例,用m/n表示。

给定两个被发送或接收的码字:

10001001

10110001        XOR(异或,exclusive OR)

00111000         3 bits不同

这两个码字中不相同的位的个数成为海明距离(Hamming distance)

它的意义在于如果两个码字的海明距离为d,则需要d个1位错误才能将一个码字转变成另一个码字。

 

具有距离的代码的界限:

2D + 1 可以纠正D错误(例如,下面的2个错误)

D + 1 可以检测D错误(例如,下面的4个错误)

为了纠正D错误,你需要一个2D + 1码的距离,因为即使D改变,原始码字仍然比任何其他码字更接近。

为了可靠地检测D错误,您需要距离D + 1码,因为D位错误不能将有效码字更改为另一个有效码字。

4个码字的示例:10位:

0000000000,0000011111,1111100000,1111111111

代码的海明距离为5,这意味着它可以纠正2个错误或者检测双倍的错。如果接收到码字0000000111并且期望只有单个或者2个错误,则接收方知道原始的码字一定是0000011111.然而,如果发生了三个错误,0000000000变成了0000000111,则以上编码就无法正确的纠正错误了。

 

第一种编码类型:海明码

事实上这个理论下限可使用海明方法获得。在海明码中,码字的位被连续编号,从最左端的位开始,紧跟在右边的那位是2,依次从左到右编号。2的幂次方的位(1,2,4,8,16等)是校验位,其余位(3,5,6,7,9等)用来填充m个数据位。这种模式如下图的海明码所示,其中包括7个数据位和4个校验位。每一个校验位强制进行模2加,或对某些位的集合,包括其本身进行偶(或奇)校验。一位可能被包括在几个校验位的计算中。若要查看在数据k位上的校验码,必须将k改写为2的幂的和。例如,11=1+2+8,29=1+4+8+16。校验某一位只需要检查那些覆盖了该位的校验位(例如,校验1、2和8位就可以确定11位是否出错)。在这个例子中我们采用偶校验计算ASCII字母“A”的校验和。

 

这种结构给出了海明距离位3的编码,意味着它可以纠正单个错误(海明码具有一位纠错能力),针对数据位和校验位小心编号的原因在解码的处理过程中表现得十分明显。当接收到一个码字,接收机重新计算其校验码,包括收到的校验码,得到的计算结果我们称之为校验结果。如果校验位是正确的,对于偶校验而言,校验结果应该是0。在这种情况下,码字才被认为是有效的。

然而,如果校验结果不为全零,则意味着检测到了一个错误。校验结果的集合形成的错误综合集,可用来查明和纠正错误。在上图中,信道上发生了1位错误,因此分别针对k=8,4,2,1的校验结果是0,1,0和1。由此得出的综合集为0101或4+1=5。按照设计方案,这意味着第五位有误。把不正确的位(这可能是一个校验位或数据位)取反,并丢弃校验位就可以得到正确的消息——A。

 

(转)例子:1000001

确定校验码的位置

校验码在二进制串中的位置为2的整数幂。剩下的位置为数据。如图所示。

位置

1

2

3

4

5

6

7

8

9

10

11

内容

x1

x2

1

x3

0

0

0

x4

0

0

1

 

求出校验位的值

以求x2的值为例。为了直观,将表格中的位置用二进制表示。

位置

0001

0010

0011

0100

0101

0110

0111

1000

1001

1010

1011

内容

x1

x2

1

x3

0

0

0

x4

0

0

1

为了求出x2要使所有位置的第二位是1的数据(即形如**1*的位置的数据)的异或值为0。即x2^1^0^0^0^1 = 0。因此x2 = 0。

同理可得x1 = 1 x3 = 0 x4 =0

位置

0001

0010

0011

0100

0101

0110

0111

1000

1001

1010

1011

内容

1

0

1

0

0

0

0

1

0

0

1

 

因此1000001的海明码为10100001001

假设位置为1011的数据由1变成了0,校验过程为:

将所有位置形如***1 **1* *1** 1***的数据分别异或。

***1: 1^1^0^0^0^0 = 0

**1*: 0^1^0^0^0^0 = 1

*1**: 0^0^0^0 = 0

1***: 1^0^0^0 = 1

以上四组中,如果一组异或值为1,说明该组中有数据出错了。***1 **1* 1***的异或都为1,说明出错数据的位置为0101

 

第二种编码类型:卷积码

卷积码编码是我们讨论的编码方法中唯一不属于块码的编码。在卷积码(convolutional code)中编码器处理一个输入为序列,并生成一个输出位序列。在块码中没有自然消息大小或编码边界。输出取决于当前的输入和以前的输入。也就是说,编码器有内存。决定当前输出的以前输入位数称为代码的约束长度(constraint length)卷积码由它们的码率(r)和约束长度(k)来标识

下图为代码称为NASA(美国航天局)卷积码,其r=1/2,k=7。

 

 

在上图中,左边每个输入位产生右边的两个输出位,输出位是输入位和内部状态的XOR和。又因为1个输入码产生2个输出码,因此码率位1/2

内部状态保存在6个内存寄存器中。每当输入一位寄存器的值就右移一位。例如,如果输入序列为111,初始状态全为0,则在输出第一、第二和第三位后从左到右的内部咋黄台变化成100000、110000和111000。对应的输出位分别是11、10和01。这个过程需要7次移位才能完全清空输入,从而不影响输出。因此,该卷积码的约束长度k=7。

卷积码的解码过程是针对一个输入位序列,找出最有可能产生观察到的输出位序列(包括任何错误)。对于较小值的k,一种广泛使用的算法是由Viterbi开发的。该算法逐个检查观察到的序列,记住每一步和输入序列的每个可能内部状态,即输入序列产生观察序列可能产生的错误。最终其中那个具有最少错误的输入序列就是最有可能的消息。

Viterbi算法的扩展适用于不确定因素,因而能提供更强的纠错功能。这种带有一位不确定性的工作方法称为软判决解码(soft-decision decoding)。相反,在执行纠错之前就决定了每个位是0或1的工作方法称为硬判决解码(hard-decision decoding)

 

第三种纠错码:里德所罗门码(略)

里德所罗门码和海明码一样,是线性块码,往往也是系统码。但与海明码不同的是:里德所罗门码对m位符号进行操作,而不是针对单个位处理。

 

第四种纠错码:低密度奇偶校验码(略)

低密度奇偶校验码(LDPC,Low-Density Parity Check)是线性块码,LDPC码中每个输出位由一小部分的输入为形成。这样使得编码可以用一个1密度很低的矩阵来表示,这也是编码名称的由来。

LDPC码比较适用于大块数据,而且具有出色的纠错能力,因而性能优于其他很多编码。

 

3.2.2 检错码

纠错编码被广泛应用与无线链路。众所周知,相比光纤,无线链路嘈杂不堪而且容易出错,如果没有纠错码,将很难从该链路中获得任何信息。然而,光纤或高品质铜线的错误率要低得多,因此对于偶尔出现的错误采用差错检测重传的处理方式通常更为有效。

我们将考察三种检错码。这些检错码都是线性的系统块码

(1)奇偶

(2)检验和

(3)循环冗杂校验(CRC)

我们在这里仅介绍第一种检测码奇偶——把单个奇偶校验位附加到数据中。奇偶位的选择原则是使得码字中比特1的数目是偶数(或奇数)。这样处理等同于对数据为进行模2加或异或操作来获得奇偶位。例如,当以偶校验方式发送1011010时,在数据末尾添加一位成为10110100.若采用奇校验方式发送1011010时,则结果为10110101。具有单个校验位的编码具有码距2,因为任何1位错误都将使得码字的奇偶校验码出错。这意味着奇偶校验码可以检测出1位错误。

 

3.3 基本数据链路层协议

为了引入协议主题,我们先从3个复杂性逐渐增强的协议开始。

(1)乌托邦式的单工协议

(2)无错信道上的单工停-等式协议

(3)有错信道上的单工停-等式协议

首先,我们假设物理层、数据链路层和网络层都是独立的进程,他们通过来回传递消息进行通信。下图给出了一个通用实现。物理层进程和某些数据链路层进程运行在一个称为网络接口卡(NIC,Network Interface Card)的专用硬件上;链路层进程的其他部分和网络层进程作为操作系统的一部分运行在主CPU上,链路层进程的软件通常以设备驱动器的形式存在

 

3.3.1 一个乌托邦式的单工协议

在这个协议中,不需要考虑任何出错的情况,数据只能单向传输。发送方和接受方的网络层总是处于准备就绪的状态。数据处理的时间忽略不计。可用的缓存空间无穷大。最强的一个条件是数据链路层之间的通信信道永远不会损坏帧或丢失帧。这个完全不现实的协议我们给它一个昵称“乌托邦”(Utopia),我们将以此作为构建后续协议的基本结构。

 

 

3.3.2 无错信道上的单工停-等式协议

现在我们将处理这样的问题:发送方以高于接收方能处理到达帧的速度发送帧,导致接收方被淹没。这种情况实际上是很容易出现的,因此协议是否能够防止它非常重要。然而,我们仍然假设通信信道不会出错,并且数据流量还是单工的。

一种解决方法是建立足够强大的接收器,使其强大到能处理一个接着一个帧组成的连续流(或者把数据链路层定义成足够慢,慢到接收器完全跟得上)。

另一种更一般化的解决方法是让接收方给发送方提供反馈信息。接收方将数据包传递给网络层之后给发送方返回一个小的哑帧,实际上这一帧的作用是给发送方一个许可,允许它发送下一帧。发送方再发出一帧之后,根据协议要求,它必须等待一段时间知道短哑帧(即确认)到达。这种延缓就是流量控制协议的一个简单例子。

 

 

3.3.3 有错信道上的单工停-等式协议

现在我们来考虑比较常规的情形,即通信信道可能会出错。帧可能被破坏,也可能完全被丢失。然而,我们假设,如果一帧在传输过程中被破坏,则接收方硬件在计算校验和时能被检验出来。如果一帧被损坏了之后校验和还是正确的,那么这个协议将会失败。

粗看起来,我们只需要在无错信道上的单工停-等式协议上增加一个计时器就能应付这个问题。发送方发出一帧,接收方只有在正确接收到数据之后才返回一个确认帧。如果到达接收方的是一个已经被损坏了的帧,则它将被丢弃。经过一段时间后发送方将超时,于是它将再次发送该帧。这个过程将不断重复,直至该帧最后完好无损地到达接收方。

 

显然,对于接收方来说,它需要有一种方法能够区分到达的帧是第一次发来的新帧,还是被重传的老帧。为了做到这一点,很显然的做法是让发送方在它所发送的每个帧的头部放上一个序号。然后,接收方可以检查它所接收到的每个帧的序号,来判断是新帧还是应该被丢弃的重复帧。

 

 

3.4 滑动窗口协议

在前面的协议中,数据帧只在一个方向上传输。而在大多数实际环境中,往往需要在两个方向上同时传输数据。实现全双工数据传输的一种方法是运行前面协议的两个实例,每个实例使用一条独立的链路进行单工数据传输(在不同的方向上)。因此,每条链路由一个“前向”信道(用于数据)和一个“逆向”信道(用于确认)组成。两种情况下的逆向信道带宽几乎完全被浪费了。

 

 

一种更好的做法是使用同一条链路来传输两个方向上的数据。毕竟,协议2和协议3已经在两个方向上传输帧,而且逆向信道与前向信道具有同样的容量。在这种模型中,从机器a到机器b的数据帧可以和从机器a到机器b的确认帧混合在一起。接收方只要检查入境头部的kind字段,就可以区别出该帧是数据帧还是确认帧

当到达一个数据帧时,接收方并不是立即发送一个单独的控制帧,而是抑制自己并开始等待,直到网络层传递给它下一个要发送的数据包。然后,确认信息被附加在往外发送的数据帧上(使用数据帧头的ack字段)。实际上,确认信息搭了下一个出境数据帧的便车,这种技术称为稍带确认(piggy backing)

当然,数据链路层不能预测未来,所以它必须采用某种自组织方法,比如等待一个固定的毫秒数。如果一个新的数据包很快就到来,那么确认就可立即被稍带回去。否则的话,如果在这段时间间隔超时之前没有新的数据包到来,数据链路层必须发送一个单独的确认帧。

 

接下去的3个协议都是双向协议,他们同属于一类称为滑动窗口(sliding window)的协议。这3个协议在效率、复杂性和缓冲区需求等各个方面有所不同。如同所有的滑动窗口协议一样,在这3个协议中,任何一个出境帧都包含一个序号,范围从0到某个最大值。序号的最大值通常是2n-1,这样序号正好可以填入一个n位的字段中。

所有滑动窗口协议的本质是在任何时刻发送方总是维持着一组序号,分别对应于允许它发送的帧。我们称这些帧落在发送窗口(sending window)内。类似的接收方也存在一个接收窗口(receiving window),对应于一组允许它接受的帧。

 

大小为1的滑动窗口,序号3位

(a)初始化;(b)第一帧发出后;(c)第一帧被接收后;(d)第一帧被确认接收后

 

发送方窗口内的序号代表了那些可以被发送的帧,或者那些已经被发送但还没有被确认的帧。任何时候当有新的数据包从网络层到来时,它被赋予窗口中的下一个最高序号,并且窗口的上边界前移一格当收到一个确认时,窗口的下边界也前移一格。按照这种方法发送窗口持续地维持了一系列未被确认的帧。上图举了这么个例子。

 

接收窗口:

序列号==窗口的下边缘

任何窗外掉落的框架都被丢弃。

 

3.4.1 1位滑动窗口协议

在讨论一般情况之前,我们先来考察一个窗口尺寸为1的滑动窗口协议。由于发送方在发出一帧后,必须等待前一帧的确认到来才能发送下一帧。所以这样的协议采用了停-等式办法

用停止和等待方式双向传送数据:

捎带确认ack要求高效率的反向数据帧

处理传输错误、流量控制、早期定时器

 

每个节点都是发送方和接收方(p4)。

 

为了显示协议交换是多么的细微,我们注意到了双方同时发送一个初始数据包时出现的一种极为罕见的情形。这种同步困难程度如下图所示。如果异常情况在发送自己的帧之前先等待A的第一帧,则会像正常情况一样,每一帧都会被接受。

然而,如果A和B同时发起通信,则他们的第一帧就会交错,数据链路层进入异常状态。正常状态下,每一帧到来后都带给网络层一个新的数据包,这里没有任何重复;在异常状态下,集市没有传输错误,也会有一半的帧是重复的。类似的情形同样发生在过早超时的情况下,集市有一方明显地首先开始传输也会发生这样的情形。事实上如果发生多个过早超时,则每一帧都有可能被发送三次或更多,严重浪费了宝贵的带宽。

同步启动[右]导致正确但较慢的操作相比于正常[左]由于重复传输

 

3.4.2 回退N协议

到现在为止,我们一直有这样的假设,即一个帧到达接收方所需要地传输时间加上确认帧回来的传输时间可以忽略不计。有时候,这种假设明显是不正确的。在这些情形下,过长的往返时间对于带宽的利用效率有严重的影响。举一个例子:考虑一个50kbps地卫星信道,它的往返传播延迟为500毫秒。我们想象一下,在该信道上用协议4(1位滑动窗口协议)来发送长度为1000位的帧。在t=0时,发送方开始发送第一帧;在t=20ms时,该帧被完全地发送出去;直到t=270ms时该帧才完全到达接收方;在t=520ms时,确认帧才回到发送方,而且所有这一切还是在最好的情况下发生了。这意味着,发送放在500/520=96%的时间时被阻塞的。换句话说,只有4%的有效带宽被利用起来了。很明显,站在效率的角度,长发送时间、高带宽和短帧这三者组合在一起就是灾难

这里描述的问题可以看作是这种规则的必然结果,即发送方在发送下一帧之前必须等待前一帧的确认。如果我们放松这一限制,则可以获得更好的带宽利用率。这个方案的基本思想是允许发送方在阻塞之前发送多达w个帧。通过选择足够大的w值,发送方就可以连续发送帧,因为在发送窗口被填满之前前面帧的确认就返回了,因而防止发送方进入阻塞。

 

为了找到一个合适的w值,我们需要知道在一帧从发送方传播到接收方期间信道上能容纳多少个帧。这种容量由比特/秒的带宽乘以单向传送时间决定,或数据链路层有责任以链路的带宽-延迟乘积(bandwidth-delay product)序列把数据包传递给网络层。我们可以将这个数量拆分成一帧的比特数,从而用帧的数量来表示。我们将这个数值称为BD。因此,w应设置为2BD+1。如果考虑发送方连续发送帧并且在往返时间内收到一个确认,那么两倍的带宽-延时就是发送方可以连续发送的帧的个数;“+1”是因为必须接受完整个帧之后确认帧才会发出

在上述例子中,具有50kpbs的带宽和250ms的单向传输时间,带宽-延迟乘积为12.5kpbs或12.5个长度为1000位的帧。因此,2BD+1是26帧。假设发送方还和以前一样开始发送0号帧,并且每隔20ms发送一个新帧。到t=520时,他已经发送了26帧,这是0号帧的确认时间正好返回。此后,每隔20ms就会到达一个确认,因此必要时发送方总是可以发送帧。从那时起,25或26个未确认的帧将始终在旅途中。换言之,发送方的最大窗口尺寸为26。

对于较小尺寸的窗口,链路的利用率将小于100%,因此发送方式成会被阻塞住。我们可以将链路利用率表示成发送方未被阻塞的时间比例:

链路利用率<=w/2BD+1

停-等式协议的w=1,如果延迟传播甚至只有一帧时间,协议效率都将低于50%。

保持多个帧同时在传送的技术是管道化(pipelining)的一个例子。在一个不可靠的通信信道上一样传送帧会引起一些严重的问题。首先,位于某个数据流中间的一个帧被损坏或者丢失,会发生什么事情呢?在发送方发现问题之前大量的后续帧已经发出,并且即将到达接收方。当损坏的那个帧到达接收方时,显然它应该被丢弃,但接收方该如何处理所有那些后续到达的帧呢?请记住,接收方的数据链路层有责任按正确的顺序把数据包传递给网络层。

有两种基本方法可用来处理管道化传输中出现的错误。

 

一种办法称为回退N(go-back-n)接收方只需要简单丢弃所有到达的后续帧,而且针对这些丢弃的帧不返回确认。这种策略对应于接收窗口大小为1的情形。换句话说,除了数据链路层必须要传递给网络层的下一帧以外,他拒绝接受任何帧。如果在计时器超时以前,发送方的窗口已被填满,则管道将变为空闲。最终发送方将超时,并且按照顺序重传所有为被确认的的帧。从那个受损或者丢失的帧开始。如果信道的错误率很高,这种方法会浪费大量的宽带。

正常情况下接收方窗口为1时错误的影响:

 

回退n帧的情形,其中接收方窗口比较大。0号帧和1号帧被正确地接受和确认。然而,2号帧被损坏或丢失。发送方并有意识到出现了问题,它继续发送后续的帧,知道2号帧的计时器超时。然后,它退回到2号帧,从这里重新发送2号、3号、4号帧等,一切从头再来。

 

3.4.3 选择重传协议

如果错误很少发生,则回退n协议可以供做得很好;但是,如果线路质量很差,那么重传的帧要浪费大量的带宽。另一种通用的处理策略称为选择重传(selective repeat)

使用这种策略,接收方将收到的坏帧丢掉,但接受并缓存坏帧后面所有的好帧。当发送方超时,它只重传那个最早的未被确认的帧。如果该重传的帧正确到达接收方时,接收方就可按序将它缓存的所有帧递交给网络层。选择重传对应的接收方窗口大于1。如果窗口很大,则这种方法对数据链路层的内存需求很大。

选择重传策略通常跟否定策略结合起来一起使用,即当接收方检测到错误(例如,帧的校验和错误或者序号不正确),它就发送一个否定确认(NAK)。NAK可以触发该帧的重传操作,而不需要等到相应的计时器超时,因此协议性能的以提高。

 

上图中(和上面是同一张图),0号帧和1号帧被正确接收,并得到确认;2号帧丢失了。当3号帧到达接收方时,那里的数据链路层注意到自己错过了一帧,所以它针对错失的2号帧返回一个NAK,但是将第3帧缓存了起来。当4号帧和5号帧到达后,它们也被数据链路层缓存起来,而没有传递给网络层,也可以确认所有这些帧(从2号帧到5号帧)。如果NAK被丢失,则发送方的2号帧计时器最终超时,发送方就会重新发送2号帧(仅仅这一帧),但是,这可能已经过了相当长一段时间。

 

顺序接收引发了一些特殊问题,这些问题对于那些按顺接受帧的协议是不用考虑的。我们用一个例子就很容易说明麻烦之处。假设我们用3位序号,那么发送方允许连续发送7个帧,然后开始等待确认。刚开始时,发送方和接收方的窗口如图所示。现在发送方发出0~6号帧。接收方的窗口允许它接受任何序号落在0~6(含)之间的帧。这7个帧全部正确地到达了,所以接收方对它们进行确认,并且向前移动它的窗口,允许接收7、0、1、2、3、4或5号帧,如图所示。所有这7个缓冲区都标记为空。

此时,灾难降临了,闪电击中了电线杆子,所有的确认都被摧毁。协议应该不管灾难是否发生都能正确工作。最终发送方超时,并且重发0号帧。当这帧到达接收方时,接收方检查它的序号,看是否落在窗口中。不幸的是,如图所示,0号帧落在新窗口中,所以它被当作新帧接受了。接收方同样返回(捎带)6号帧确认,因为0~6号帧都已经接收到了。

 

发送方很高兴地得知所有它发出去的帧都已经正确地到达了,所以它向前移动发送窗口,并立即发送7、0、1、2、3、4和5号帧。7号帧将被接收方接收,并且它的数据包直接传递给网络层。紧接着,接收方的数据链路层进行检查,看它是否已经有一个有效的0号帧,它发现确实已经有了(即前面重发的0号帧),然后把内嵌的数据包作为新的数据包传递给网络层。因此,网络层得到了一个不正确的数据包。协议失败!

这个问题的本质在于:当接收方向前移动它的窗口后,新的有效序号范围与老的序号范围有重叠。因此,后续的一批帧可能是重复的帧(如果所有的确认都丢失了),也可能是新的帧(如果所有的确认都接收到了)。可怜的接收方根本无法区分这两种情形。

解决方法:确保接收方向前移动窗口后,新窗口与老窗口的序号没有重叠。为了保证没有重叠,窗口的最大尺寸应该不超过序号空间的一半。

 

 

3.5 数据链路协议实例

这里要考察的是那些出现在Internet两种常见情形下的数据链路协议,这些协议主要用在点到点的线路上。第一种情形是通过广域网中的SONET光纤链路发送数据包。

第二种情形是运行在Internet边缘的电话网络本地回路上的ASDL链路。

 

3.5.1 SONET上的数据包

为了在这些链路上承载数据包,需要某种成帧机制,以便将偶尔出现的数据包从传输它们的连续比特流中区分出来。运行在IP路由器上的PPP就提供了这种运行机制,如下图所示:

 

PPP帧格式如下图所示:

所有的PPP帧都从标准的HLDC标志字节0x7E(01111110)开始。标志字节若出现在Payload字段,则要用0x7D去填充;然后将紧跟在后面的那个字节与0x20进行XOR操作,如此转义使得第6位比特反转(相当于加密)。

紧跟在帧开始处标记字节的后面出现的是Address字段。这个字段总是被设置为二进制值11111111,表示所有站点都应该接受该帧。使用这个值可以避免如何为数据链路层分配地址这样的问题。

Address字段后面是Control字段,其默认值是00000011.辞职表示一个无编号帧。

Flag和Address字段都是默认值,可去除。

第4个字段是Protocol字段。他它的任务是通告Payload字段中包含了什么类型的数据包。以0开始的编码定义为IP版本4、IP版本6以及其他可能用到的网络层协议,比如IPX和APPLETALK。以1开始的编码被用于PPP配置协议。

Payload字段是可变长度的,最高可达某个协商的最大值。

Checksum字段,通常占2个字段,但可以协商使用4个字节的校验和。

 

在通过SONET线路发送PPP之前,必须建立和配置PPP链路。PPP链路的启动、使用和关闭的一系列阶段如图所示:

 

链路的初始状态为DEAD(死),这意味着不存在物理层连接。当物理连接被建立起来链路转移到 ESTABLISH(建立)状态。此时,PPP对等实体交换一系列的LCP报文进行上面所说的那些PPP选项的协商,这些LCP报文放在PPP帧的 Payload字段。初始发起连接的实体提出自己的选项请求,对等实体可以部分或者全部接受,甚至全部拒绝,同时它也可以提出自己的选项要求。

如果LCP选项协商成功,链路状态进入 AUTHENTICATE(认证)状态。现在,如果需要,双方可以互相检查对方的身份。如果认证成功,则链路进入 NETWORK(网络)状态,通过发送一系列的NCP包来配置网络层参数。NCP协议很难一概而论,因为每个协议特定于实际采用的某个网络层协议,允许执行针对特定于该网络层协议的配置请求。例如,对于IP协议而言,为链路的两端分配IP地址是最重要的可能操作。

一旦进入OPEN(打开)状态,双方就可以进行数据传输。正是在这个状态下,IP数据包被承载在PPP帧中通过 SONET线路传输。当完成数据传输后,链路进入 TERMINATE(终止)状态:当物理层连接被舍弃后从这里回到DEAD状态。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值