数据链路,顾名思义,数据链路就是链路来传输数据,也就是物理链路+逻辑链路(协议,或者说规程)来传输数据,物理硬件对应着网络适配器。
在网络结构中,数据链路层位于网络的倒数第二层,也就是在物理层上面一层,负责比较简单的转发,主要有两种模式,点对点和广播。点对点使用ppp协议,广播使用csma/cd模式。
数据链路层比较傻,只会局部的转发,而且是通过mac地址,所以头脑简单,不过转发比较发达。做的工作无非就是上面有任务包装一下,下面有事情上传以下,保证自己不出错就好。所以是哪个主要的问题就是封装成帧,透明传输和差错检测。
封装成帧就是上面有任务说,小数据链路子啊,你来给我传这么个消息下去,于是,小数据链路就加上开头结尾什么的soh(start of header)还有eot(end of transmission)就传出去了,加上开头结尾就防止了这个消息被人家理解不能,不知道什么时候说完没。
透明传输就是不用在乎传的是什么,老佛爷传输,才不管总管怎么说呢!于是数据链路的目的就是尽可能的使得说的话不会和开头结尾冲突啊,但是这么一些消息你怎么知道呢?其实就是加个转义字符啦!
差错检测,其实主要有两部分,第一种是消息内部某比特传输错误了,这个其实加个校验就成,第二个就是传输的数据没错,但是丢包啦,重复啦,失序啦这些问题。首先第一个错误,防止中间的比特出错,那么就使用crc这个方法来加个余数,然后传输的东西就成了原始数据加上一个检验,是不是感觉可靠多了啊,原理类似于下载文件的md5等,就是为了一个验证。如果不能匹配,那就丢掉好啦。第二个错误,就是防止丢包、重复、失序等问题,那就编号,确认,重传这个机制,不过来来回回交互太多,太慢,所以在网络情况不太好的时候用这种方法还成,现在我们的网络都这么可靠了,一般也就不靠数据链路层干这个了,如果有错误的,不管了,交给上层。让tcp去解决。
好啦,这下就完美啦!上层的ip数据报包装一下,加个fcs校验,再加个头尾,然后就丢出去,收到的帧拆开看看对不对,然后再丢给上层。
下面就说一说和点对点协议ppp相关的内容,在很久很久以前有一个高级数据链路控制hdlc但是因为太复杂了,因此有一个简单得多的ppp协议。这个协议干啥的呢?比如说我们个人电脑连接到购买了服务的isp上,那么我们首先要建立连接,比如说我们要说好,连上物理线路,我要发包啦,数据链路层负责我电脑的消息能够传递到isp上,然后剩下的如果这个包继续传输的话,还要约定ip等内容,配置网络层相关参数,这样才能够使得我的电脑能够自由的上网。而这一切的一切都是要通过ppp协议开始。
我们在宽带上网的时候总会有个pppoe的配置,就是point
to point over Ethernet的缩写。这个协议将会使得千家万户开始连接互联网。这个协议公布于1999年。
假设我们要来制定协议,那么我要提出什么要求呢?首先,要简单,就是一个底层的传输,也不用太多思考,就是发就好了,所以简单就好,能检查错误,丢弃出错的帧。再有就是之前所说的封装成帧,对上层要透明,要支持很多的网络协议,要支持多种物理的链路,还要能够有协商的东西,比如说我们发消息的时候用一种帧来表示,开始配置网络的时候要用另一种方式来表示。类似于电脑启动时候的bootloader和启动之后的操作系统使得。总之要有环境,然后才干正事儿。
所以ppp协议有这么三个部分。第一个部分是正常的传输ip数据报,第二部分是来配置链路相关参数的lcp,第三部分是配置网络的ncp。这其实符合我们最开始的设想,首先我们要链接的时候,先要本层相关的东西配置好,这就要用到lcp,配置好了之后,相邻的两个节点就已经畅通了,那么就要开始配置能不能在互联网上遨游了,这时候就要更高层次的网络层的配置,通过ncp来表示。都好了之后,我的电脑到isp的链路好了,我的电脑在以太网上的ip地址也有了,我就能去玩耍了,这时候发送的消息就是正常的ip数据报的消息了。
所以这个协议的三种不同的组成部分刚好对应了真实的建立连接的过程。
既然ppp协议的这个帧能够做这么三件事儿,那么具体怎么来实现呢?
首先要有头有尾,这样才能够区分是不是,所以有个flag来标记,而且非常对称,0111 1110,这样来表示开始和结束。在开始的部分还有就是表示这个数据报是什么类型的,是lcp还是ncp还是包含ip数据报,这其实是在开头的协议子段来决定的,在尾部还有一部分就是fcs。
所以五个有用的部分,flag protocol data fcs flag。当然,在head中还有两部分没有什么大用,分别是address和control。
在传输的时候有这么几点需要考虑,首先就是传输是同步还是异步,如果是同步,那么就是一个比特一个比特的传输,如果是异步,那么就是一个字节一个字节的传输,再这样的传输的时候就带来一个问题,我的其中有些报文中的内容可能和我的最后的开始和结束的flag重复了怎么办,这样可能导致我错误的分段了。那么在传输的时候呢,如果是异步的,我们就可以像是转义字符似的来对于我们的数据流进行处理,这样似的任何可能的“嫌疑字节”都被特殊标记出来,不会被误认,这个方法叫做字节填充。如果是同步的一个比特一个比特的传输,那么就把如果有连续的5个1,就在第五个1后面加一个0,比如11111->111110,接收的时候如果遇到了五个1,自动去掉后面的一定有的一个0就好,这样就避免了在数据中存在6个1的情况,使得我的数据肯定不会有flag在其中,这叫做零比特填充,对于这种填充的方式是通过硬件来实现的,所以不会有什么效率上的问题。
当我打算建立链接的时候,我首先在物理上进行连接,然后通过lcp配置相关报文的参数,最后通过ncp配置网络参数。
在配置lcp中,首先要确定双方的鉴别协议,就是我想链接你,但是不行啊,你不让,不是谁都能链接的啊,所以要商量一下协议,通过了,好,继续谈接下来的ncp的事情,不通过那就没戏了。
在通过了鉴别之后,就是可以来进行网络层的设置了,比如说通过ncp中的ipcp协议来配置ip相关的数据。
不用这个链路的时候按照ncp,lcp最后是物理链接的顺序逐渐断开就好。