把数据帧从链路的一端正确的传输至另一端。
主要有两种:
在一段数据的前后分别添加首部和尾部,这样就构成了一个帧。这样是为了识别物理层上交的比特流中识别一个帧的开始和结束(帧定界)。
分组交换的一个重要概念就是:所有在互联网上传送的数据都以分组(IP数据报)为传送单位。网络层的IP数据报到达数据链路层后作为帧的数据部分,再加上首部和尾部,就构成了完整的帧。
在发送帧时从帧首部开始,为了提高帧的传输效率,不同数据链路层协议规定了所能传送帧的数据部分长度上限—最大传送单元MTU(Maximum Transfer Unit),例如以太网为1500Bytes,并且对于帧的首部和尾部的格式也有明确的规定。
当帧的数据部分是ASCII码组成的文本文件时,帧定界可以使用特殊的帧定界符。首部开始可用SOH(Start Of Header)【0x01】表示,帧结束可用EOT(End Of Transmission)【0x04】来表示。(因为文本文件都是可打印字符,也就是键盘可以输入的,这两个定界符属于不可打印字符,不会与数据冲突)
有了定界符,就可以检测一个帧是否完整,从而选择是否丢弃。
如果帧的数据是二进制数据(比如二进制代码或图像),在数据中很有可能会出现与定界符一样的数据,那么这时候就不能正确的确定帧的界限,可能会造成错误的接收(提前找到了EOT)或错误的丢弃(找不到SOH)。
透明的意思是:让某一个实际存在的事物看起来好像不存在一样,那么在数据链路层就代表了忽略错误的定界符,按照原样传送数据。
为了做到透明就要想办法使数据部分可能出现的“SOH”和“EOT”在接收端不被解释为控制字符。解决方案就是在其前加上转义字符“ESC”【0x1B】。在接收端的数据链路层把数据送至网络层之前删除这个添加的转义字符。这种方法成为字节填充(bytes stuffing)或字符填充(character stuffing)。
如果数据中出现了转义字符,解决方案仍然是在其前面插入转义字符,因此当接收端收到连续的两个转义字符时,就删除前面的一个。
通信链路不会是理想的。比特传输过程中很可能产生比特差错:0变为1,1变为0。其中错误比特数与传输的比特总数的比值称为误码率BER。误码率与信噪比有很大关系,降低信噪比就可以降低误码率。但是总会存在干扰,所以为了保证可靠传输,就必须采用检错机制。
循环冗余检验CRC是数据链路层广泛使用的检错技术。
假定每组数据k个比特,待传送数据为M,收发双方实现商定(n+1)位的除数p,CRC运算就是在M后面添加n位冗余码,相当于添加n个0。最终发送方一共发送(k+n)位。虽然增大了传输开销,但是可以避免差错,这是很值得的。
在发送端:用(k+n)位除以商定好的p,得到商Q余数R(n位),Q每什么用处,而R则作为帧检测序列FCS添加在M后发送出去。
例如M=101001,p=1101,则n=000,用101001000除以p,得到Q=110101,R=001,则最终发送的数据为101001001。
在接收端:把收到的数据以帧为单位进行CRC检验:每一帧除以p(模2运算),如果余数R=0则没有出现比特差错,则接收,否则就丢弃(无法确定哪些位出现差错)。
还有一种简便方法来表示循环冗余检验过程:生成多项式,但归根结底还是上述例子,就不展开。
注意:发送端的FCS和接收端的CRC检验都是硬件完成,所以速度很快不会延误数据传输。
那么使用了CRC的数据链路层实现了可靠传输吗?并没有,因为可靠传输指的是无传输差错,也就是发送的什么就原样的接收到什么,而CRC只能做到接收到的帧是无差错的,也就是做到了无比特差错而不是无传输差错。 传输差错还有很多,比如帧丢失、帧重复、帧失序,比特差错只是其中一种。
过去OSI的观点是必须让数据链路层向上提供可靠传输,因此在CRC基础上添加了帧编号、确认和重传机制。但现在通信链路的质量已大大提升,所以对于通信质量良好的有线传输链路,不适用确认和重传机制,即不提供可靠传输,对于通信质量较差的无线链路,则像上提供可靠传输服务。