3.1 使用点对点信道的数据链路层
本节讨论使用点对点信道的数据链路层的一些基本问题。其中的某些概念对广播信道也是适用的。
3.1.1 数据链路和帧
在这里要明确一下,“链路”和“数据链路”并不是一回事。
所谓链路(link)就是从一个结点到相邻结点的一段物理线路,而中间没有任何其他的交换结点。在进行数据通信时,两台计算机之间的通信路径往往要经过许多段这样的链路。可见链路只是一条路径的组成部分。
数据链路(data link)则是另一个概念。这是因为当需要在一条线路上传送数据时,除了必须有一条物理线路外,还必须有一些必要的通信协议来控制这些数据的传输(这将在后面几节讨论)。若把实现这些协议的硬件和软件加到链路上,就构成了数据链路。现在最常用的方法是使用网络适配器(如拨号上网使用拨号适配器,以及通过以太网上网使用局域网适配器)来实现这些协议的硬件和软件。一般的适配器都包括了数据链路层和物理层这两层的功能。通常将网络适配器简称为网卡。
早期的数据通信协议曾叫做通信规程(procedure)。因此在数据链路层,规程和协议是同义词。
下面再介绍点对点信道的数据链路层的协议数据单元——帧。
数据链路层把网络层交下来的数据构成帧发送到链路上,以及把接收到的帧中的数据取出并上交给网络层。在因特网中,网络层协议数据单元就是IP数据报(或简称为数据报、分组或包)。
为了把主要精力放在点对点信道的数据链路层协议上,可以采用如图3-1(a)所示的三层模型。在这种三层模型中,不管在哪一段链路上的通信(主机和路由器之间或两个路由器之间),我们都看成是结点和结点的通信(如图中的结点A和B),而每个结点只有下三层,即网络层、数据链路层和物理层。
图3-1 使用点对点信道的数据链路层
点对点信道的数据链路层在进行通信时的主要步骤如下:
(1)结点A的数据链路层把网络层交下来的IP数据报添加首部和尾部封装成帧。
(2)结点A把封装好的帧发送给结点B的数据链路层。
(3)若结点B的数据链路层收到的帧无差错,则从收到的帧中提取出IP数据报上交给上面的网络层;否则丢弃这个帧。
数据链路层不必考虑物理层如何实现比特传输的细节。我们甚至还可以更简单地设想好像是沿着两个数据链路层之间的水平方向把帧直接发送到对方,如图3-1(b)所示。
3.1.2 三个基本问题
数据链路层协议有许多种,但有三个基本问题则是共同的。这三个基本问题是:封装成帧、透明传输和差错检测。下面简单介绍这三个基本问题的要点。
1.封装成帧
图3-2表示用添加帧首部和帧尾部封装成帧的概念。我们知道,分组交换的一个重要概念就是所有在因特网上传送的数据都是以分组(即IP数据报)为传送单位的。网络层的IP数据报必须向下传送到数据链路层,成为帧的数据部分,同时它的前面和后面分别添加上首部和尾部,然后封装成一个完整的帧。帧的长度等于帧的数据部分长度加上帧首部和帧尾部的长度。首部和尾部的主要作用是进行帧定界,同时也包括必要的控制信息。在发送帧时,是从帧首部开始发送的。各种数据链路层协议都要对帧首部和帧尾部的格式有明确的规定。显然,为了提高帧的传输效率,应当使帧的数据部分的长度尽可能大些。但是,每一种链路层协议都规定了帧的数据部分长度的上限,即最大传送单元MTU(Maximum Transfer Unit)。图3-2表示帧的数据部分不能超过规定的MTU数值。
图3-2 用帧首部和帧尾部封装成帧
2.透明传输
既然帧的开始和结束是使用专门指明的“帧首部”和“帧尾部”来进行标记的,那么在帧首部和帧尾部之间的数据部分就不允许出现和帧首部或帧尾部一样的比特组合,否则就会是帧定界的判断出错。如果数据部分碰巧出现了和帧首部或帧尾部一样的比特组合,那么数据链路层协议就必须设法解决这个问题(即在这样的比特组合之前再增加一个事先约定好的控制字符,然后在接收端在读取数据时再删除发送端所增加的控制字符)。
如果数据链路层协议允许所传送的数据可具有任意形式的比特组合(即使出现了和帧首部或帧尾部标记完全一样的比特组合,协议也会采取适当的措施来处理),那么这样的传输就称为透明传输(表示任意形式的比特组合都可以不受限制地在数据链路层传输)。
3.差错检测
现实的通信链路都不会是理想的。这就是说,比特在传输过程中可能会产生差错:1可能会变成0,0也可能变成1。在一段时间内,传输错误的比特占所传输比特总数的比率称为误码率BER(Bit Error Rate)。例如,误码率为10-10时,表示平均每传送1010个比特就会出现1个比特的差错。误码率与信噪比有很大的关系。如果设法提高信噪比,就可以使误码率减小。实际的通信链路并非理想的,它不可能使误码率下降到零。因此,为了保证数据传输的可靠性,在计算机网络传输数据时,必须采用各种差错检测措施。目前在数据链路层广泛使用了循环冗余检验CRC(Cyclic Redundancy Check)的比特检错技术,其原理图如图3-3所示。
图3-3 循环冗余检验CRC的原理
图3-3中,发送方先把数据划分为固定长度的组(也就是要传送的分组),然后在数据的后面添加n位的帧检验序列FCS(Frame Check Sequence)。通常n=16或32,但为了提高传送效率,n应当远小于数据部分的长度。帧检验序列是经过简单的除法运算得出的。方法是:先在数据的后面添加n位的0,然后作为被除数送到除法器进行运算。除数有(n+1)位,是经过精心挑选的。通过除法器的运算,最后得出的n位的余数就是我们所需要的帧检验序列。
顺便说一下,CRC和FCS并不是同一个概念。CRC是一种检错方法,而FCS是添加在数据后面用来检错的冗余码;在检错方法上可以选用CRC,但也可不选用CRC。
接收方把接收到的数据以帧为单位进行CRC检验:把收到的每一帧都送到除法器进行运算(除以和发送方生成FCS时所使用的同样除数),然后检查得到的n位余数。
如果在传输过程中未出现差错,那么经过CRC检验后得出的余数肯定是零。于是这样的帧就被接受下来。但当出现差错时,则余数将不为零,这样的帧就被丢弃。
严格来讲,当出现误码时,余数仍有可能等于零,但这种概率是极小的,通常可以忽略不计。因此只要余数为0,就可以认为没有传输差错。
总之,在接收方对收到的每一帧经过CRC检验后,若得出的余数为零,则判定该帧没有差错,就接受(accept);若余数不为0,则判定该帧有差错(但无法确定究竟是哪一位或哪几位出现了差错),就丢弃。
显然,如果数据不以帧为单位来传送,那么就无法加入冗余码以进行差错检验。
最后再强调一下,在数据链路层若仅仅使用CRC差错检测技术,则只能做到无差错接受,也就是说,凡是接收方数据链路层接受的帧均无传输比特差错。
但是,无传输比特差错并不等于可靠传输。所谓“可靠传输”就是:数据链路层的用户在发送方发送什么,在接收方就收到什么。这不仅表明在接收方所接受的帧中的每一个比特都和发送的帧一样,而且所有收下的帧都无丢失、不重复,同时顺序还和发送的一样。例如,发送方发送了100个帧,但这些帧在到达接收方后,能通过CRC检验的只有1个帧,那么接收方就只接受这1个传输无比特差错的帧。这种情况仍然属于“无比特差错接受(凡接受的均无比特差错)”,但远远不是“可靠传输”,因为发送的100个帧中有99个帧由于出现差错而被接收方丢弃了。
过去曾经流行的OSI观点是“数据链路层必须提供可靠传输的服务”。因此在CRC检错的基础上,又增加了确认和重传机制。接收方收到正确的帧就要向发送方发送确认。发送方在一定的期限内若没有收到对方的确认,就认为出现了差错,就要进行重传,直到收到对方的确认为止。这种方法在历史上曾广为流行。但现在的有线通信线路的质量已经大大提高了,因此因特网广泛使用的数据链路层协议都不使用确认和重传机制(使用有线信道),即不要求数据链路层向上提供可靠传输的服务(因为这要付出的代价太高,不上算)。当上层传输的数据必须要可靠地传送到对方,可以在运输层使用具有可靠传输功能的TCP协议。在第9章要介绍的无线局域网,由于信道质量不太好,因此采用可靠传输协议。