-
前面学习了第一层,我们知道了物理层的大致作用,了解了用线缆构建一个网络,并知晓了相关设备。
那么如何从一台设备向另一台设备发消息?
要达到这个目的,光靠第一层的硬件显然是不够的。
OSI第二层的作用
作为大名鼎鼎的“数据链路层”,其作用有:使局域网中机器相互连接,侦测传输错误 。他还有个著名的“跟班”:交换机(也就是常说的Switch)
注意,这里说的是“侦测”,而不是“修正”。
MAC地址——唯一标识
目前网络上的情况稍有复杂:虽然有时我们想和所有机器通信(好比现实世界中对着大家说话),但是大部分时候,我们每次都是与单独的一台机器通信。
那么,“茫茫机海中,我与谁相逢 ?” …
为了定位某台机器,就需要给每台机器一个:“身份证”了。网络的先驱们于是在OSI的第二层创建了一个标识,用于标明每一台机器“是谁”,这个标识被称为 MAC地址。
但其实,并不是每一台机器都有一个(独立的)MAC地址作为标识。
大家想啊,既然我们处于OSI第二层,离第一层只有“咫尺之距”,因此MAC地址是和硬件设备有关的 —— 网卡。
网卡上最令我印象深刻的就是连着的RJ45接口(母头)。
可以说,MAC地址其实是网卡的地址,而不是每台机器的地址。因此,MAC地址用于在网络中唯一标识一个网卡,一个电脑会有一个或多个网卡,每个网卡都有自己的MAC地址。
MAC地址的概念
说起来,我们还要找“二进制”好好聊聊!
之前笔者提到过,在信息技术领域,我们用0和1来代表电信号的高电平和低电平,或说两种状态(开/关)。
计算机中的许多元件都可以达到这两种状态,分别用0和1表示,用来计算或存储数据。
例如半导体通电表示1,不通电表示0,CPU等半导体芯片就是这样计算的。这样运算 的有点便是 统一标识、规则简单、节省设备。
MAC地址以十六进制编码
十六进制想必也不用多说,由0-9、A-F共同构成的字码。
而MAC通常表示形式如下: 00:0c:29:10:5a:55
MAC地址编码
如上表示,MAC地址以6个字节编码(48个二进制位),每两个字节由冒号隔开。
一个字节(Byte)是指明一定量的数据的信息元。例如:一个500GB的硬盘,其实就是500个G的Byte的容量。G是英语giga的意思,表示千兆,即十亿,10的9次方。因此500GB就有大约500000000000个字节。
为什么说“大约”?
精确来看,1GB=1024MB=1024X1024KB=1024X1024X1024B,而硬盘厂商设计时按1GB=1000MB近似计算。
但是现在有个问题,我们如何保证每一块网卡的MAC地址不会和世界上已经存在的网卡地址重复呢?难道不会搞错吗?
一般来说不必考虑此问题。因为一个网卡制造商会购买MAC地址,更确切地说是MAC地址的区块。
MAC地址最前面三个字节是IEEE分配的,后面三个字节由制造商自行分配。这样的话,只要生产商保证自己生产的每块网卡后面使用不同的三个字节,就不会有重复MAC地址了。
特殊的MAC地址
在众多的MAC地址中,有一个地址很特殊——其每一个二进制位都是1: ff:ff:ff:ff:ff:ff
它被称为 广播地址 。
广播,广而播之。顾名思义,广播地址可以代表任意一个网卡,因此发向广播地址的信息就会发送到所在网络的所有网卡上。
好了,现在我们既已知晓如何用OSI第一层将机器连起来,并用第二层来标识每一台机器(的网卡)。那么是时候定义一个互通所需的语言了。
链路层的语言——以太网协议
它规定了机器之间交换信息的格式。
在网络中,我们通常将通信所用的语言成为“协议”。
在第二层众多的协议中,我们“一眼看中了” Ethernet,即以太网 。 以太网协议并不是第二层中唯一的协议,但却是最常用的。
协议的作用
网络是为了交换信息而生的,网络中传输的都是0/1这样的二进制数据。因此,我们极有可能收到如下信息:
0110101110110101100011001
但是就轮到我们懵逼了。这什么鬼…
协议就是被用来定义用什么样的信息、以什么样的顺序传输。
在传输的信息里,要包含:
- 发送方地址
- 接收方地址
- 信息的实际内容
这样的一个信息单元的总,术语称之为 帧 (数据帧)。帧是OSI第二层中传输的数据单元,可以将其看做数据包。
以太网中帧的形式
现在有一个问题:在一个帧中,到底是发送方的MAC地址在前还是接收方的在前?
为了回答这个问题,我们需要换位思考,想象自己就是那台接收信息的机器。
对于机器来说,发送方的 MAC 地址和接收方的 MAC 地址,哪一个更有价值呢?
网络的先驱者们认为接收方的 MAC 地址对一台机器来说更有价值,因为可以立即得知信息是不是发给我们的。如果信息是发给我们的,那么我们阅读信息;如果不是发给我们的,那么大可不必理会。
因此我们在一个帧中,将接收方的 MAC 地址(也叫 MAC 目标地址)放在前,后面跟着发送方的 MAC 地址(也叫 MAC 源地址)。目前我们的以太网帧大致如下:
我们知道,OSI七层模型在发送发发送信息时,需要从上到下依次穿过OSI各层:
就是说,在穿越第 2 层前,我们需要穿越第 3 层,这样,第 3 层就可以告诉第 2 层在第 3 层使用的协议是什么了。
这很有用,因为当信息到达接收方的时侯,接收方的机器的第 2 层首先检验 MAC 目标地址,如果和自己的 MAC 地址一样,那么接收方的机器的第 2 层需要将信息发送到第 3 层的对应协议。
在接收方,需要反向穿越 OSI,如下图所示:
至此,我们的以太网帧变成了这样:
还没完!
和一个完整的帧段相比,还缺了:
- 要发送的信息本身
- 错误检测
我们应该将这两个信息放在第3层时候用的协议后面。
不少人应该会对“错误检测”感兴趣:CRC
什么是CRC ?
CRC 是循环冗余校验(Cyclic Redundancy Check)的缩写,这名字也比较抽象。
CRC 是一个数学的值,可以作为要发送的数据的一种代表。
简单说来,CRC 对于每条发送的信息都是不一样的。发送方使用某公式计算出被传送数据所含信息的一个 CRC 值,并将此值附在被传送数据后,接收方则对接收到的同一数据进行相同的计算,得到另一个 CRC 值。
如果这两个 CRC 一致,说明发送中没有出错;如果不一致,说明发送中出现了差错,接收方可要求发送方重新发送该数据。
假设机器 A 发送一条信息给机器 B:
- 发送前,机器 A 根据发送的信息,来计算 CRC 值(假设值为 X),将这个值放在一帧的结尾处;
- 机器 B 接收到 机器 A 发送来的一帧数据后,也计算一个 CRC 值(假设值为 Y);
- 机器 B 比较自己计算出来的 CRC 值(Y)和机器 A 发送过来的帧中的 CRC 值(X);
如果 X 和 Y 相等,说明机器 A 发送的帧和机器 B 收到的帧是一样的;
如果 X 和 Y 不相等,说明发送时出了问题,机器 A 发送的帧和机器 B 收到的帧不一样,就成功检测到了错误
现在我们有了完整的元素,那么我们完整的一帧也就可以“画出”:
一帧的大小是多少?
在一帧中,有些元素的大小(尺寸)是不变的。这些元素的集合我们称之为帧头。下图中的粗体表示帧头里的数据:
帧头的格式是固定的,因此我们可以定义其大小:
接收方和发送方的 MAC 地址分别占用 6 个字节;
第 3 层的协议用 2 个字节编码;
CRC 用 4 个字节编码。
6 x 2 + 2 + 4 = 18。
因此以太网的帧头一共有 18 个字节。
当然,也有一种分法是将一帧分为帧头、数据部分、帧尾三部分。接收方和发送方的 MAC 地址和第 3 层使用的协议作为帧头,而 CRC 作为帧尾。
当然了,一帧是有最小尺寸和最大尺寸的 —— 以太网帧的最小尺寸是64字节,最大尺寸是1518字节。
小结:在机器 A 和机器 B 之间交换数据的过程如下:
- 机器 A 上的一个应用(application,在 OSI 的第 7 层应用层,以后我们会学习应用层)想要发送数据到机器 B 的应用上;
- 在 机器 A 这个发送方这端,此数据从上到下穿过 OSI 的各层;
- 到底3层了,发送方的第 3 层去告知第 2 层所使用的协议是什么;
- 第 2 层用这些信息,包装成一个帧,通过网络传输;
- 机器 B 收到了机器 A 发送的这个帧,首先检查帧头部的第一个元素:接收方的 MAC 地址;
- 如果等于机器 B 的 MAC 地址,那么机器 B 读取帧中接下来的信息;
- 依据帧中的协议部分,接收方(机器 B)的第 2 层就把数据正确地发送给第 3 层;
- 数据在接收方就从下到上,直达机器 B 的应用了。