某年某月某一天,我在WLW上写了半篇没CTRL+S的博文 深研《TCP/IP详解卷1》——链路层,突然间室友做饭搞个功率很大的电磁锅弄的跳闸了,停电了!于是一段很长的篇幅就这样被这无情的断电给抹杀了。。能做的只有:从头再来!
TCP/IP协议的分层封装实现使得每一层看起来像是完全独立特行的,以至于我们可以认为不同主机间每一层的数据传递直接是两个同层的传递,这意味着我们可以完全忽视所有中间过程而把注意力集中在我们关注的层次;比如两个不同主机间链路层的帧传递我们仅需要关注这一层即可,以至于底下的物理层线路怎么去传递的,可以完全不用关心。对于链路层而言,其主要作用有三点:
(1)接收和发送IP层传来的数据;
(2)为ARP模块接收应答和发送ARP请求;
(3)为RARP模块接收RARP应答和发送RARP请求;
ARP和RARP是两种比较重要的地址解析协议,在此先将其视为同IP层在一个层次的协议向下发送或向上传递(链路层)数据,相应的链路层对其进行应答。既然链路层要发送和接收数据,它就必须对数据进行处理:即封装成符合要求的帧;链路层比较常见的两种处理协议时:SLIP协议和PPP协议。对于PPP协议倒是个很熟悉的字眼了。而令我一直不解的是:国内绝大部分大学计算机网络教科书中对于现今依然普遍使用的SLIP协议却只字不提,亦或许仅仅是所谓的大纲要求吧。。 链路层各种协议都遵循3个基本原则:封装成帧,差错检测和透明传输;以下会详细探讨,我的文章不会按照卷一书中的的讲解顺序去记录每个知识点,搞不懂缘何TCP/IP的作者总是提前提出很多未知名词并大加引用,到了之后的章节才进行这种名词解释的写作习惯,MTU就是个很好的例证,它在本章节近乎最后的地方才解释,却在之前用过很多次了:
MTU(最大传输单元)
每种链路层协议都会规定其所限定的最大传输数据段长度,这便是MTU。以太网和RFC 802.3分别对MTU值的限定是:1500和1492字节(注意这并不意味着MTU只能是这么大),当IP层传下来的数据段或从底层获取的数据段大于这个长度时,这便会造就帧丢失的情况。所以IP层在想下层传递数据时,必须先将数据进行分片。至于具体分片原则会在后续有关IP层的章节说明。
原则1:分装成帧
将数据封装成帧即在一段数据的前后分别加上帧头SOF和帧尾EOT,以此便形成了完整的帧。如下图所示(真实的帧结构比这复杂些,在此说明3个原理时进行了简化处理,以下2个原则不再进行说明):
特别注意MTU并非指帧的最大长度,通常而言是指除掉帧头和帧尾之外的中间数据最大长度。由于数据有了开始和结束符,于是在传送过程中若是突然出现了中断,那么可能会出现只有帧头没有帧尾的情况,如此的话当数据传送到下一个数据链路时由于检测到不是一个完整的帧,便可以直接扔掉此帧。
原则2:透明传输
现在假定,SOH和EOT的编码都是0XEE,那么如果所要传送的数据部分出现了一个0XEE,这便会出现帧边界出错的情况,如下图所示:
链路层在处理数据时会误把数据部分的SOH(OXEE)当成是界定符来处理,于是后面的部分数据部分SOH后面部分便会被丢掉而没有传输。为了处理这种帧由于数据部分出现帧边界的情况,于是就引入了类似C语言中转义字符的处理方式。C语言中的转义字符为“\”,在这里我们假定用ESC来充当这种转义字符,那么在数据部分便会被处理成如下这样的格式:
这样的话,当数据传送到下个数据链路层进行处理的时候,每读到一个ESC,其后的SOH就不会被认定为一个界定符了。倘若数据段中也出现一个纯内容的ESC呢?处理方式也类似,即直接在其前面增加一个ESC字符,当下一个数据链路层接收到两个ESC字符时,便会删除其中一个。
原则3:差错检测
实际的帧结构比上面的要复杂些,可能会如下所示(卷一原图):
这是RFC 802.3规定的帧结构,除了数据段外,不仅仅只有帧头和帧尾那么简单。目前我们只需关心最后的CRC段,这部分由4个字节表示,是通过一种CRC运算得出的检验码,对于CRC运算的具体方法其实比较简单,在此我不进行详述,可以去看看(这里)。 其本质类似于我们平时对一些数据进行MD5加密,只不过CRC运算的结果肯定为0,当接收端接收到数据后使用同样的方式进行检测,得到的结果若为0则证明传输没有出现差错,如果不为0则肯定出现了差错,于是丢掉当前帧。这样的话,可以看到链路层的这种检错传输机制保证了传输到目的主机的帧肯定是正确的(因为错误的帧都会被丢弃)。
SLIP协议
这种协议的用途在卷一中一笔带过,百度百科对其解释是“SLIP(Serial Line Internet Protocol,串行线路网际协议),该协议是Windows远程访问的一种旧工业标准,主要在Unix远程访问服务器中使用,现今仍然用于连接某些 ISP。因为SLIP协议是面向低速串行线路的,可以用于专用线路,也可以用于拨号线路,Modem的传输速率在1200bps到19200bps”。
事实上,这是种比较简单的协议,其基本结构类似于在上述 原则2 中讲解的结构,对帧的处理方式也一样,但没有目标地址,没有CRC段,也没有类型段,于是便出现了以下三个缺点:
(1)没有办法把本端的IP地址通知给另一端;
(2)没有办法进行帧校验,如果传输过程中可能由于线路噪声而改变了某些数据的值(把0变为1或1变为0),这些校验工作也必须由链路层的上层来完成;
(3)由于没有类型段,所以一条线路不能同时传送SLIP和其它类型的链路层协议(如PPP),因为不同协议对帧的封装方式不同,造就同一个数据传送段被封装成不同的帧,倘若一条用于SLIP传送的线路同时传送SLIP和PPP协议的帧类型,那么到达目的主机的链路层后便全部当做SLIP协议的帧封装格式进行解析,所造就的后果不堪设想。
CSLIP协议(压缩的SLIP协议)
假如我们需要用SLIP协议传送一个字节数据的帧,那么经过上层(IP层和运输层)的处理后,最终到达链路层的数据会达40个字节,其实主要是加些协议首部,后续章节会详述。CSLIP协议通过某种压缩处理把通常数据段较小的SLIP协议压缩成很简短的帧,从而大大提高了传输效率。在这里40个字节或许会被压缩成3到5个字节进行传输,从而大大提高了运行效率。而今基本所有的SLIP协议的产品均支持CSLIP协议。
PPP协议(点对点协议)
相较于SLIP的所有缺点而言,PPP协议则没有任何其所具有的缺点。通常我们通过拨号连接于某个ISP(internet service provider,互联网服务提供商,如电信)连接时,便用到这个协议。对于PPP协议的帧结构如下图:
开始和结尾的标志字段便是前面原则1所说的SOF和EOT了,固定为0XFF。地址段和控制段均是固定的0XFF和0X03。而协议段通常用来指定数据段的类型,0X0021表示为IP数据报,0XC021表示链路控制数据,0X8021表示网络控制数据。
同样的,PPP协议也遵循 原则2;相较于SLIP而言,其所具有的优势如下:
(1)由于协议段的存在,其支持在单根串行线路上传输多种协议,不只是IP协议;
(2)有了CRC校验,保证了数据传输的正确性;
(3)与CSLIP类似,可以对帧进行压缩处理;
环回接口(LookBack接口)
卷一种并没有详细说明环回接口的原理,只是单纯的说明了其进行数据传送时所经过的线路原则。环回接口通常只是个虚接口(IP地址),由于一个路由器有多个接口,如果其中一个接口中断了连接,则可以通过其它接口来访问这个路由器。若为一个路由器选择一个接口作为其唯一标示,而这些物理接口又可能会随时DOWN掉,于是得重新选择一个接口作为其ID。环回接口就是用来标示一个路由器的唯一ID,可进行手动指定,不会随物理接口状态的变化而变化。
之所以把环回接口也放到链路层是因为其所充当的角色类似于一个链路层。当网络层把一个数据传送到一个环回接口时,通常会出现以下三种情况:
(1)传给环回地址的数据直接会被返回到IP输入队列中,即直接会传送到IP层;
(2)传给广播或多播地址的数据通常会复制一份到环回接口(即传给自己),因为广播或多播定义本身包含主机本身;
(3)任何传给当前主机IP地址的数据均送到环回接口。
事实上,如果一个主机在给自己传送数据,那么这些数据永远不会被传送到网络上,因为很多以太网设备驱动都不能都回它们发出去的数据。这也便要求一个主机必须能处理自己发送出去的数据。
链路层,到此结束!
今晚的风,好凉快……