计算机网络是很重要的一部分知识,之前也认为很难,因为要分那么多层(五层或七层),而且每一层还有自己的功能和协议,一大堆的东西很不好学;但是后来发现了一个很好的学习方法,就是先熟悉每一层的作用,然后再顺着思考他为了实现这个功能要怎么办?要使用哪些协议?这样不仅能帮助很好的理解,也能很高效的去学习。
首先,了解过计算机网络的同学都知道,计算机网络的每一层都是基于下层提供的服务为上层提供服务的,所以数据链路层是在物理层提供的服务上向网络层提供服务的;因此数据链路层的作用是将源自网络层来的数据可靠地传输到相邻节点的目标机网络层,简单的说就是把上层(网络层)给我数据传输给目标计算机的网络层。那么,为了达到这一目的,数据链路层应该具备一系列的功能:如何将数据组合成数据块;如何控制帧在物理信道上的传输,包括如何处理传输差错,如何调节发送速率以使之与接收方相匹配;在两个网路实体之间提供数据链路通路的建立、维持和释放管理。其具体表现为一下这些方面。
组合成数据块?我们都知道数据链路层的传输单位是帧,那么解决的办法就是将网络层传来的数据封装成帧。
封装成帧就是在一段数据的前后分别添加首部和尾部,让其构成一个帧。接收端在收到物理层上交的比特流后,就可以根据帧首部和尾部的标记找到帧;如图所示:
从图中我们可以看出来,帧的数据部分越是大于帧首部和帧尾部传输的效率就会越高;因此, 为了提高帧的传输效率,通常会使使帧的数据部分长度尽量大于首部和尾部的长度,但是帧数据的部分也不是无限大的,肯定要有一个最大值来对其进行限制,那就是MTU(最大传输单元),决定了帧数据部分长度上限。
当数据是由可打印的ASCII码组成的文本文件时,帧定界可以使用特殊的帧定界符。通常,帧首部和帧尾部也会有特定的控制字符,控制字符**SOH(start of header,二进制是00000001)放在一帧的最前面,表示帧的首部开始。另一个控制字符EOT(end of transmission,二进制是00000100)**表示帧的结束。
采用帧传输方式的好处是,在发现有数据传送错误时,只需将有差错的帧再次传送,而不需要将全部数据的比特流进行重传,这就在传送效率上将大大提高。
透明传输也是数据链路层的一个重点,但是什么是透明传输?又该怎么理解呢?这个定义看似简单,如果不明白的话就会疑惑为什么是透明?是怎样透明的?透明传输表示无论什么样的比特组合的数据,都能按照原样没有差错的通过这个数据链路层,就是无论所传的数据是什么样的比特组合,都可以进行传送;并不是说传送数据的是“透明的”,就好像现在现在的快递一样,快递小哥负责给你派送包裹,但是他并不管你的包裹里面是什么东西(前提必须是合法的呀)。
那么问题来了,这样难道就不会出现问题吗?当然是会的。通常会出现这两个问题:
既然透明传输会出现问题,那我们就一定要有防范的措施,那就是在组帧的时候进行一些处理,避免这些情况,具体方法有四种。
帧首部使用一个计数字段( 第一个字节,八位 )来标明帧内字符数
使用这种方法一定要确保计数字段的准确性,否则将造成严重的后果
当传送的帧是由非ASCI码的文本文件组成时( 二进制代码的程序或图像等 )。就要采用 字符填充 方法实现透明传输;如果所传的数据中有与帧定界符一样时,就在前面填充ESC,这种方式和 Java 里面的的转义字符很相似,具体实现过程如下;
在发送端,扫描整个信息字段,只要连续5个1,就立即填入1个0;在接收端收到一个帧时,先找到标志字段确定边界,再用硬件对比特流进行扫描。发现连续5个1时,就把后面的0删除。
由于字节计数法中Count字段的脆弱性(其值若有差错将导致灾难性后果)及字符填充实现上的复杂性和不兼容性,目前较普遍使用的帧同步法是比特填充和违规编码法。
前面我们说了将数据封装成帧和透明传输,但是传输的时候还是会不可避免的产生一些问题,所以接下来就要进行差错控制。既然要进行差错控制,我们就要先知道会出错的情况:传输过程中可能会产生比特差错(1 可能会变成 0 而 0 也可能变成 1),帧(包括发送帧和响应帧)出错或者帧(包括发送帧和响应帧)丢失。具体的检错措施有以下几种。
CRC运算实际上就是在长为 k 的数据后面添加供差错检测用的 n 位冗余码,然后构成 k+n 位的帧发送出去。在了解 CRC 之前要先知道几个概念:
计算过程
现假定待传输数据 M=101001(k=6),生成多项式为 1101,计算其最终应该发送的数据:
位置 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---|---|---|---|---|---|---|---|---|---|---|---|
内容 | x1 | x2 | 1 | x3 | 0 | 1 | 0 | x4 | 1 | 1 | 0 |
3. 求出校验位的值
以求x2的值为例。为了直观,将表格中的位置用二进制表示。
位置 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 |
---|---|---|---|---|---|---|---|---|---|---|---|
内容 | x1 | x2 | 1 | x3 | 0 | 1 | 0 | x4 | 1 | 1 | 0 |
为了求出x2,要使所有位置的第二位是1的数据(即形如1 的位置的数据)的异或值为0。即x2^ 1^ 1^ 0^ 1^0 = 0。因此x2 = 1。
同理可得x1 = 0, x3 = 1, x4 = 0。
位置 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 |
---|---|---|---|---|---|---|---|---|---|---|---|
内容 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
因此1010110的海明码为01110100110。
上面我们已经解决了数据传输前和接收到数据后验证的工作,接下来就要对数据传输的过程进行控制;主要是对传输过程进行流量控制,就好像我们的公路一样,路已经建好了,如果不制定交通规则(靠右行驶、红绿灯),那么即使再好的路、再好的车一天你也不可能走的很远,因为大家都按照自己的想法来行驶,所以都被堵在了路上。具体流量控制的方法有下面这几种。
停止-等待协议(发送窗口=1,接收窗口=1):每发送完一个帧就停止发送,等待对方的确认,在收到确认之后再发送下一个帧;接收方每接收一帧 , 都要反馈一个应答信号 ,表示可接收下一帧,如果接收方不反馈应答信号,则发送方必须一直等待。每次只允许发送一帧 ,然后就陷入等待接收方确认信息的过程中 ,因而传输效率很低 。具体的几种情况如图所示
1、**后退N帧协议(GBN):**发送窗口>1,接收窗口=1;若采用n个比特对帧编号,那么发送窗口的尺寸WT应该满足:1≤WT≤2n-1,因为发送窗口过大,就会使得接收方窗口无法区别新帧和旧帧。发送方要做的三件事:
接收方要做的事情:
2、**选择重传协议(SR):**发送窗口>1,接收窗口>1; 若采用n比特对帧编号,为了保证接收方向向前移动窗口后,新窗口序号与旧窗口序号没有重叠部分,需要满足条件:接受窗口+发送窗<=2^ n;由此我们可以推得:发送(或接收)窗口大小 <= 2^(n-1)。发送方必须做的三件事:
接收方要做的事情:
我们都知道数据链路层进行的传输也是可靠传输,那么他是如何实现可靠传输的呢?
数据链路层的可靠传输通常使用确认和超时重传两种机制来完成 。确认是一种无数据的控制帧,这种控制帧使得接收方可以让发送方知道哪些内容被正确接收。有些情况下为了提高传输效率,将确认捎带在一个回复帧中,称为捎带确认 。超时重传是指发送方在发送某一个数据帧以后就开启一个计时器 ,在一定时间内如果没有得到发送的数据帧的确认帧 ,那么就重新发送该数据帧,直到发送成功为止 。
前面我们已经讨论了很多东西,但是关于数据传输的链路我们还是不太清楚,是点对点的?还是广播的?当然是点对点和广播的都有,不同的链路所使用的的协议肯定是不一样的,我们再来学习一下这两种方式以及所使用的的协议吧。
首先,我们要先了解PPP协议,ppp协议不需要纠错,不需要设置序号,不需要进行流量控制,不支持多点线路(既一个主站轮流和链路上的多个从站进行通信),只支持点对点的链路通信,只支持全双工链路。PPP协议是由三部分组成的:
CSDA/CD协议的主要内容有三方面,载波监听、多点接入和碰撞检测;下面就分别进行解释:
这些均为个人总结,只是采用这种方式去理解数据链路层的功能,还有很多别的重要的知识点没有提及,如果有兴趣欢迎相互交流;也欢迎提出问题。