
大家好,很高兴又和大家见面啦!!!
在上一篇内容中,我们初步探索了数据链路层的基本功能和核心作用。数据链路层作为网络体系结构中的关键一环,不仅负责将物理层提供的原始比特流组织成有意义的传输单元,还要确保数据在相邻节点间高效、可靠地传输。 今天,我们将深入探讨数据链路层的一个基础且至关重要的技术——组帧(Framing)。 简单来说,组帧就是为网络层下发的数据包“穿上外衣”,添加必要的首部和尾部,形成数据链路层能够识别和处理的传输单元。这个过程之所以必不可少,是因为它解决了通信中的一个根本问题:
理解了组帧,你就能明白数据链路层是如何为上层提供一条看似无差错的数据通道的。现在,让我们一同揭开这项关键技术的面纱。
组帧(Framing)是指将来自网络层的分组(数据报)添加首部和尾部,封装成一个帧的过程。这个帧是数据链路层的数据传输单元。 在通信的过程中,发送方会依据一定的规则将网络层递交的分组封装成帧,并以其为传输单位进行传输。这是为了保证在出错时只需要重发错的帧,而不必重发全部数据,从而提高传输效率。 组帧主要解决帧定界、帧同步、透明传输等问题。实现组帧的方法通常有以下4种:
接下来我们来逐一了解这四种组帧法;
字符计数法是指在帧首部使用一个计数字段来记录该帧所含的字节数(包括计数字段自身所占用的1字节)。
flowchart LR
subgraph A[组帧]
subgraph B[计数字段]
b[0000 0111]
end
subgraph C[数据部分]
direction TB
c[0000 0000]
d[0000 0001]
e[0000 0010]
f[0000 0011]
g[0000 0100]
h[0000 0101]
end
end就如上图所示的组帧,其数据部分总共有 6 个字节的数据,但是通过字符计数法进行组帧时,该计数字段所记录的字节数为 7。这是因为字符计数法中的计数字段所记录的帧的总字节数为:
当接受方读取帧首部的字节字数值时,就知道后面跟随的字节数,从而确定帧结束位置。因为在传输过程中,帧与帧之间时连续传输,所以也能确定下一帧的开始位置。
当我们使用该方法进行组帧时,就需要面临一个最大的问题:
这是因为在字符计数法中,计数字段除了记录该帧的字节总数,同时他还是帧边界划分的依据:
flowchart LR
subgraph A[组帧]
direction TB
subgraph B[计数字段]
b[5]
end
subgraph C[数据部分]
direction TB
c[0]
d[1]
e[2]
f[3]
end
end
subgraph A1[组帧]
direction TB
subgraph B1[计数字段]
b1[5]
end
subgraph C1[数据部分]
direction TB
c1[4]
d1[5]
e1[6]
f1[7]
end
end
A--->A1当计数字段出错时,接收方就无法准确判断帧的结束位置以及下一帧的起始位置:
flowchart LR
subgraph A[组帧]
direction TB
subgraph B[计数字段]
b[3]
end
subgraph C[数据部分]
direction TB
c[0]
d[1]
e[2]
f[3]
end
end
subgraph A1[组帧]
direction TB
subgraph B1[计数字段]
b1[5]
end
subgraph C1[数据部分]
direction TB
c1[4]
d1[5]
e1[6]
f1[7]
end
end
A--->A1
classDef red fill: #ff9999, color: #000, stroke: #ff0000, stroke-width: 2px
class e red就如上图所示,当第一帧中的计数字段因为错误而导致其记录的字节数从 5 变成 3 时,原先作为数据的字节,就会被误识别为计数字段。因此该组帧方法的健壮性是比较差的。
字节填充法是指使用特定字节来定界一帧的开始与结束。
flowchart TB
subgraph A[组帧]
direction TB
a[SOH:0000 0001]
b[数据部分]
c[EOT:0000 0100]
end如上所示,控制字符 SOH (Start Of Header) 放在帧的最前面,表示帧的开始;控制字符 EOT (End Of Transmission) 放在帧的最后面,表示帧的结束。
不管是 SOH 还是 EOT ,其都有特定的二进制序列:
SOH = 0000 0001EOT = 0000 0100因此当接收方识别到 0000 0001 时,就找到了该帧的开头;当识别到 0000 0100 时,就找到了帧的结尾;
正因为 SOH 和 EOT 有特定的二进制序列,那么当数据部分中同时存在该序列时,就会导致接收方识别错误; 为了防止帧的数据部分中存在的 SOH 和 EOT 不被识别为帧的首尾定界符 ,因此发送方会在数据部分的特殊字符前填充一个转义字符 ESC (Escape Character) 来加以区分,以实现数据的透明传输。 与 SOH 和 EOT 一样,ESC 同样有特定的二进制序列:
ESC = 0001 1011接收方在数据部分识别到该序列时,就知道后面紧跟的特殊字符为数据信息,而不是控制信息。
同理,当数据部分本身就含有该序列时,发送方也会在该序列前再加一个转义字符:
flowchart TB
subgraph A[组帧]
direction TB
a[SOH]
subgraph B[数据部分]
direction TB
b[ESC]
c[SOH]
d[ESC]
e[ESC]
f[ESC]
g[EOT]
end
h[EOT]
end
classDef red fill: #ff9999, color: #000, stroke: #ff0000, stroke-width: 2px
class b red
class d red
class f red如上图所示,只要是出现在数据部分的特殊字符,在进行数据传输时,发送方都会在其特殊字符前再填充一个转义字符,用以告诉接收方当前的特殊字符为数据内容。
零比特填充法 指的是用一个特定的比特串 01111110 来标志一帧的开始与结束。
flowchart TB
subgraph A[组帧]
direction TB
a[01111110]
b[数据部分]
c[01111110]
end如上图所示,该方法同样通过特殊的二进制序列来标志帧的开始和结束,正因如此,该方法同样存在与 字节填充法 相同的问题:
但是在 零比特填充法 中对该问题的处理与 字节填充法 的处理并不相同;
在 零比特填充法 中,为了使数据部分的二进制序列 01111110 不被识别为帧的首尾标志,发送方会在发送数据之前,先对其进行一次扫描,每当扫描到连续的 5 个 1 时,就会自动在其后填充一个 0 :
flowchart TB
subgraph A[组帧]
direction TB
a[01111110]
subgraph B[数据部分]
direction TB
b1[0000 0000]
b2[0000 0000]
b3[0111 11]
b4[0]
b5[10]
b6[1111 1]
b7[0]
b8[101]
end
c[01111110]
end
classDef red fill: #ff9999, color: #000, stroke: #ff0000, stroke-width: 2px
class b4 red
class b7 red如上图所示,当数据部分中存在连续的 5 个 1 时,就会在其后面填充一个 0 ,这样就可以保证数据部分不会出现连续的 6 个 1 ,自然也就规避了 0111 1110 的识别错误。 而接收方在接收数据时,每当在数据部分识别到了连续的 5 个 1 就会自动删除后面紧跟的 0 ,以恢复原始数据。 在数据链路层早期使用的 HDLC 协议和现在广泛使用的 PPP 协议均使用的是 零比特填充法。 该方法很容易由硬件实现,其性能优于字节填充法。
违规编码法 指的是通过违规编码序列来定界帧的起始与终止。 该编码方法需要物理层的配合,如物理层采用的是 曼彻斯特编码 ,即每个码元中间都会发送电平的跳变:
10而对于该编码法而言,当某个码元中间未发送跳变时,则该码元的编码方式是 违规的 ,此时我们将这种违规的编码插入到数据的开头与结尾,就可以作为帧的起始和终止。 局域网 IEEE 802 标准就采用了这种方法。 违规编码法不采用任何填充技术便能实现数据的透明传输,但只适用于采用冗余编码的特殊编码环境。 因为 字符计数法 中计数字段的脆弱性和 字节填充法 实现上的复杂性与不兼容性,所以目前常用的组帧方法是零比特填充法 和 违规编码法。
通过本文的探讨,我们了解到组帧是数据链路层的一项核心任务,其目的是将网络层的数据包封装成帧,实现高效可靠的数据传输。
核心要点总结
🔷 组帧的核心价值
🔷 主流组帧方法比较
01111110 定界,通过"遇5个 1 插 0"规则实现透明传输
技术价值
掌握不同的组帧方法,特别是理解帧定界与透明传输的实现机制,是深入理解数据链路层工作原理的重要基础。