数据链路层
数据链路层的功能
加强物理层传输原始比特流的功能,提供逻辑链路的功能,使得数据链路层上层的网络层能够透明地传输数据。
我爱小图~
- 为网络层提供服务
- 组帧和透明传输
- 差错控制
- 流量控制
- 链路管理(连接的建立、维持、释放,主要用于面向连接的)
- 在广播链路中使用MAC 地址寻址,实现多路访问控制
根据类别不同,提供给网络层的服务分为三种
- 无连接的无确认的服务(适用于实时通信且误码率低的信道,比如直播)
- 无连接的有确认的服务(适用于误码率较高的信道)
- 面向连接的有确认的服务(适用于对实时性与可靠性要求高的场合,适用于长距离且不可靠的链路)
值得注意的是,面向连接必须要 ACK
Framing 组帧
将网络层传来的数据添加首部和尾部,形成帧,帧是数据链路层传输的基本单位。
由于噪声的影响,发出的比特流可能会遭到破坏,检错和纠错是数据链路层的重要功能。而通常的做法是针对一小段比特流进行检错和纠错。
因此,将整个比特流拆分成一个个的帧,对每一帧进行检错和纠错,这样就可以保证数据的可靠传输。
字节计数法
利用帧头的一个字段(一个字节)标识该帧中的字符数目
然而,这个数目也可能会出错,如果出错,接收方就会失去同步,往后的所有帧都会出错。
字节填充法
使用标志字节来标识帧的开始和结束,如果在数据中出现了标志字节,就在前面加一个转义字符,接收方收到转义字符后,就会忽略这个字符。
也就是说,有两个特殊的字符ESC
和 FLAG
,如果帧数据单元中出现了这两个字符,就在前面加一个ESC
,接收方收到ESC
后,就会忽略这个字符,并启用常规录入模式录入后续的一个字节。
比特填充法
帧的划分如果使用字节填充法,那么在数据中出现的标志字节就会被转义,这样会增加数据的长度,同时FLAG
使用一个字节过于奢侈。
于是,比特填充法依旧使用一个标志字节01111110
,但是在数据中出现了连续的 5 个1
时,就会在后面加一个0
,接收方收到01111110
后,就会忽略这个字符。
这样保证了数据中不会出现标志字节,同时是用最少的填充比特。
违例码
直接使用物理层没有使用过的码字作为帧的开始和结束标志,这样就不会出现在数据中出现标志字节的情况。
比如:曼彻斯特编码中,11
/00
作为帧的开始和结束标志。或者 4B/5B 编码中,11110
作为帧的开始和结束标志。
差错控制
前向纠错 FEC:在发送端添加冗余信息(纠错码),接收端通过冗余信息检测并纠正错误。
后向纠错 ARQ:接收端检测到错误后,请求发送端重发。
冗余信息的构建思想:假设数据为 \(d\),冗余信息为 \(r\),我们需要构建一个函数
这样一个函数要满足如下的性质,g 为检错函数:
Hamming Distance
两个等长的字符串之间的汉明距离是两个字符串对应位置上不同字符的个数。
为了可靠的检测\(d\)个错误,需要满足系统中的任意两个码字之间的汉明距离至少为\(d+1\)。
- 说明:如果两个码字之间的汉明距离为\(d\),那么至少需要\(d+1\)个错误才能使得错误码字变为正确码字。
为了可靠的纠正\(d\)个错误,需要满足系统中的任意两个码字之间的汉明距离至少为\(2d+1\)。
- 说明:\(d\)个错误发生时,能够保证至少有一个码字的汉明距离\(\leq d\),其他的码字的汉明距离都大于\(d\),这样就可以通过检错找到错误的位置。
如果我们需要纠正 1 位错误,原始数据的位数为\(m\),我们需要添加的冗余位数为\(r\),每一个原始数据都对应着\(m+r\)个距离为 1 的码字,而冗余数据的位数为\(r\),所以有:
检错码-奇偶校验码
添加一位偶校验位,使得整个数据的 1 的个数为偶数。
能够保证正确的码字之间的汉明距离为 2,于是能够检测出 1 位错误。
检错码 checksum
将数据分成若干个块,每个块的和为 1 个字节,然后将所有的和相加,得到一个字节,这个字节就是校验和。
接收方收到数据后,也计算校验和,如果两者不相等,就说明出现了错误。
然而,这种方法只能检测出一部分错误,而不能检测出所有的错误。
Example:
def checksum(data):
res = 0
for i in range(0, len(data), 2):
res += int(data[i:i+2], 16)
return res
```
### 检错码-CRC 循环冗余校验码
1. 多项式阶数:$n$ 位的多项式,阶数为 $n-1$
2. 生成多项式:$G(x)$
3. 生成校验码:$R(x)$
4. 检错:$R(x) \mod G(x) = 0$
生成多项式是给定的,接收方收到数据后,计算出校验码,然后计算出 $R(x) \mod G(x)$,如果结果为 0,说明没有错误。
而校验码的生成过程是这样的:
- 假设数据为 $D(x)$,先将 $D(x)$ 左移 $n$ 位,然后除以 $G(x)$(模二除法,XOR),得到余数 $R(x)$,将 $R(x)$ 加到 $D(x)$ 后面,就得到了校验码。
如果在传输过程中出现错误,即接收方收到的数据为$R(x) + E(x)$,那么计算出的余数就为$E(x) \mod G(x)$,如果$E(x)$恰好是$G(x)$的因子,那么余数就为 0,否则就会出现余数不为 0 的情况。
### 纠错码-Hamming 码
将校验码插入在序号为 2 的幂次方的位置上,这样就能够保证正确的码字之间的汉明距离为 3,能够纠正 1 位错误。
采用如下的规则:
- 1 的位置为校验位
- 2 的位置为校验位
- 4 的位置为校验位
- ...
生成规则(偶校验规则):
- 1 的位置为校验位,二进制第 1 位的值为 1 的个数为偶数
- 2 的位置为校验位,二进制第 2 位的值为 1 的个数为偶数
- 4 的位置为校验位,二进制第 3 位的值为 1 的个数为偶数
- ...
纠错规则:
如果获得的码字中,校验位的值与校验规则不符,那么就说明出现了错误,然后通过校验位的位置,就可以找到错误的位置。
## 流量控制
在数据链路层,可靠传输与流量控制是同时处理的。
可靠传输(顺序、丢失、错误)在数据链路层中是通过 ARQ + 超时重传实现的
流量控制是为了防止发送方发送的数据速度过快,导致接收方无法处理(buffer 不够,使得发送的数据被迫丢弃)。
### 停止等待协议
假设信道是可靠的情况下
发送方发送一个帧后,等待接收方的确认帧,如果接收方收到了帧,就发送确认帧,否则就丢弃。
而如果要增加错误纠正的功能,就要实现 ARQ 以及添加序号
1. ARQ:自动重传请求,接收方收到正确的帧后,发送确认帧 ACK,否则丢弃,等待超时重传
2. 添加序号:对于接收方来说,需要对接收到的帧确认是是重传的帧还是新的帧,所以需要添加序号(因为可能会存在 ACK 丢帧,发送方认为超时)
要考虑的问题:
1. 超时时间的选择:起码要大于一个往返时间 RTT,可以设定为$\text{Time Out}> 2 \cdot \text{Propogation Delay}$,但是其实在处理过程中,信源需要校验和缓存(发送和排队),信宿需要校验和重传,所以实际的超时时间会更长
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240613191305141-979467168.png)
$$
U = \frac{T_D}{T_D + RTT + T_A}
$$
信道利用率 $U$ 与传输时间 $T_D$、往返时间 RTT、传输时间 $T_A$ 有关
为了使信道利用率提高,即当发送方发送完一个帧后,在 RTT 内仍旧可以发送下一个帧。
### 滑动窗口协议
滑动窗口协议是为了提高**信道利用率**的同时实现**流量控制**,并捎带**可靠传输**,即在接收方确认帧之前,发送方可以发送多个帧。
我们使用一组长度为$n$的序号,发送方和接收方都维护着一个窗口,发送方维护着一个发送窗口,接收方维护着一个接收窗口。
在任何时刻发送方总是维护着一组序号,这组序号中的帧是已经发送但是还没有收到确认的帧,这些帧落在发送窗口内
接收方维护着一组序号,这组序号中的帧是已经收到但是还没有确认的帧,这些帧落在接收窗口内
**最基本的要求**是,数据包发送的顺序和接收的顺序是一致的
### GBN 协议
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240613192519182-288155185.png)
然而,可以采用**累计确认**的方式,即接收方只需要确认最后一个正确的帧,发送方就可以知道之前的帧都已经收到了。
发送方需要维护一个发送窗口与超时计时器,如果接收到 ACK,就将窗口向前滑动,并 reset 超时计时器,如果超时,就重传窗口内的所有帧。
接收方需要维护一个期望接受的帧序号,同时接受到正确的帧后,发送 ACK,如果接收到的帧序号**不是期望的帧序号**,就丢弃,一直等待期望的帧序号。
**GBN**的接收方滑动窗口大小为 1,发送方滑动窗口大小为 $1 \leq W \leq 2^n -1$,不能为$2^n$的原因是,如果为$2^n$,当发送方重传时,接收方无法区分是新的帧还是重传的帧。
### SR 协议
GBN 协议当发生错误的时候,由于接收方窗口为 1,所以需要批量重传
而我们可以设置单个确认,同时加大接收窗口,让没有确认的帧保留,只重传错误的帧
需要注意的是,等待确认的必须是窗口内的第一个帧,如果不是,就需要等待,直到窗口内的第一个帧被确认。否则超时重传待确认的帧。
而接收方也一样,需要维护一个接收窗口,只有接收到的帧是期望的帧,才会发送 ACK,否则就放置于接收窗口中,等待期望的帧;如果检测错误,就发送 NAK,要求重传
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240613200102160-809803887.png)
滑动窗口大小:
- 发送方与接受方的窗口大小相等
- 发送方+接受方的窗口大小不超过 $2^n$,即要求发送方与接收方的窗口不会有重合
## HDLC 协议
与下面的 PPP 协议一样,用于广域网的数据链路层协议,提供可靠的数据链路服务,支持全双工通信。
与 PPP 不同,HDLC 是一种**面向比特**的协议,而 PPP 是一种**面向字节**的协议。同时 HDLC 支持重传与确认,是可靠的数据链路服务。
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240617203701561-1676346669.png)
## PPP 协议
PPP 协议是一种数据链路层协议,用于在两个点之间建立连接,是一种**面向字节**的协议。
包括三个组成部分
- LCP:链路控制协议,用于建立、配置、测试数据链路连接
- NCP:网络控制协议,用于配置网络层协议
- 包装 IP 数据报
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240614141853439-692990942.png)
- 标志字段:`01111110`,用于标识帧的开始和结束(PDU 要进行相应的字节/比特填充的处理)
- 地址字段:通常为 `11111111`,表示广播地址
- 控制字段:通常为 `00000011`,表示无编号数据帧
- 协议字段:表示上层协议,如 IP 协议为 `0x0021`
- FCS 是帧校验序列,用于检测帧的错误,通常使用 CRC 校验。(提供的是**不可靠的数据链路服务**,并且也不提供编号服务,但是网络层会要求重传)
PPP 链路从建立到关闭的状态图
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240614142709445-1282157641.png)
值得注意的是,链路在建立的时候进行协商,协商的内容**包括发送速率**、接收速率、协议等。
## 动态信道分配
在没有源宿的总线设计中,多个站点共享一个信道,这就需要介质访问控制,隔离其他站点,动态的分配信道,以避免同时发送的碰撞。
### 纯 ALOHA
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240613201408960-860955445.png)
### 时隙 ALOHA
控制发送时间的随意性
把时间分成若干个相同的时间片,每个时间片称为一个时隙,每个站只能在时隙开始时发送数据帧,如果在时隙开始时发送的数据帧与其他站发送的数据帧冲突,就会发生碰撞,需要等待下一个时隙再次发送。
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240613201531262-407378767.png)
### CSMA 协议
CS:**载波侦听**,即检测总线上是否有信号
MA:多路访问,争用总线
当发生碰撞时,碰撞的地方会发出一个信号,这样其他站点和要发送信息的站点就会知道发生了碰撞,然后**等待一个随机的时间**再次发送。
这也就是说,载波监听检测总线空闲时,总线不一定是空闲状态,那么就会发生碰撞,这时候两个发送站点都等待随机时间再次发送。
也分为两种:
- 1-persistent CSMA:如果信道空闲,就发送,如果信道忙,就等待
- p-persistent CSMA:如果信道空闲,以概率$p$发送,以概率$1-p$推迟到下一个时间槽,如果信道忙,就等待一个随机时间再次发送
- 非坚持 CSMA:如果信道空闲,就发送,如果信道忙,就等待一个随机时间再次侦听
### CSMA/CD
CD:碰撞检测
需要分析发生碰撞时,站点在什么时刻能够检测到碰撞信号
![20240614150316](https://cdn.jsdelivr.net/gh/Blackteaxx/Graph@master/img/20240614150316.png)
那么$2\tau$就被称为争用期,是一个重要参数
其实也就是说,在争用期之内,发送方的发送时延不能少于争用期,否则发送方就无法检测碰撞并使用协议重发。
因此会有帧长下限的问题,即**帧长相应的发送时延不能小于争用期**。
也会有帧长上限的问题,导致总线总是很忙,因此需要设置帧长上限。
### 二进制指数后退
工作原理是,在**基本退避时间的基础**上,乘了一个随机数,减少碰撞的概率。
$$
\text{Backoff Time} = 2\tau \times \text{Random Number}\\
\text{Random Number} = \text{rand}(0, 2^i - 1) \\
i = \min(\text{重传次数}, 10)
$$
## 以太网
是局域网的一种,是一种广播信道,所有的站点共享一个信道,使用 CSMA/CD 协议。
以太网使用了分配技术解决局域网中了广播/多路访问的问题,与 PPP 不同的是,以太网(IEEE 802.3)解决的是一个局域网中拥有很多计算机的问题,因此需要使用地址标识
### MAC 地址
当多个主机连接在同一个广播信道上时,需要使用 MAC 地址来标识不同的主机,即每一个主机都要有一个数据链路层地址。
通常被称作物理地址/硬件地址,由 48 位二进制数组成,前 24 位是厂商编号,后 24 位是厂商内部编号。
### 以太网帧格式
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240614152417605-2013698189.png)
以太网的数据链路层没有重传机制,是无连接的,因此需要网络层的重传机制。
在以太网协议中,MAC 帧传给物理层仅需要一个前导码和 SOF,不需要帧尾。
## 无线局域网 WLAN
协议标准:IEEE 802.11,也被称为 Wi-Fi
一个非常重要的特点就是他的误码率比以太网高,因此需要使用更加复杂的纠错码/检错码
同时可能会有暴露站和隐藏站的问题,即信号范围导致的不知道是否有其他站点发送数据
无线局域网不能使用 CSMA/CD 协议,因为无线信道是半双工,且检测碰撞的信号强度很低,无法检测碰撞,所以采用了 CSMA/CA
### CSMA/CA
这样一个操作模式被称作:DCF(分布式协调功能),在 DCF 方式下,没有中心控制站点,每一个站点使用 CSMA/CA 协议来争用信道决定何时发送数据。
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240614154441291-1527984585.png)
- 考虑 DIFS 间隔是可能有其他的站有高优先级的数据要发送
- 帧首部会有一个 NAV 字段,表示信道被占用的时间(包括目的站发回确认帧的时间)
- 发送方会有一个计时器
- 如果某一个站检测到信道中传送的帧首部持续时间字段时,就会调整自己的网络分配向量 NAV,使得其他站在这段时间内不会发送数据(虚拟载波监听机制)
- SIFS 是短间隔时间
- ACK 是确认帧,是由于无线信道误码率较高,需要停等
- 随机退避时间是为了减少发生碰撞的概率
- 为了进一步减少碰撞的概率,源站在发送数据帧之前,会发送一个 RTS 帧,包括源地址、目的地址、本次通信所需的持续时间
- 目的站收到 RTS 帧后,会发送 CTS 帧(也包括持续时间),表示自己已经准备好接收数据
- 使用 RTS/CTS 进行信道预约,是为了减少碰撞重传时候的发送时延浪费,也可以为了**解决暴露站和隐藏站**的问题
### 无线局域网的 MAC 帧
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240614174952086-1005917637.png)
- 持续时间:用于 CSMA/CA 的预约机制,在数据帧、RTS、CTS 都有
- 序号:用于重传机制中的可靠传输
- FCS:帧校验序列,用于检测帧的错误
- 地址:1 是下一站的地址,2 是出发地址,3 是最终的目的地址,4 是源地址
地址的分配取决于去往 DS 与来自 DS 的标志位
![img](https://img2023.cnblogs.com/blog/3436855/202406/3436855-20240614175807534-122460713.png)