PPP协议:解填充的魔术手法,是把多余的糖果变不见!🍬

在数据链路层协议(如PPP)的语境下,数据载荷(Payload) 就是指它所承载的、来自网络层的数据包(例如IP数据报),不包含PPP协议自身为了成帧而添加的帧首部和帧尾部(比如标志字段F、地址A、控制C、协议P、校验FCS等)。

这道题的核心就是考察你是否掌握了PPP协议为了实现透明传输而采用的**字节填充(Byte Stuffing)**机制,以及如何进行其逆操作——解填充(Unstuffing)
Pasted image 20250814104655.png


字节填充与解填充——透明传输的幕后英雄

一、 一切的起点:为何需要“透明传输”?

想象一下,你正在写一封信,信的结尾处需要写上“全文完”三个字作为结束标记。但如果你的信件内容本身就包含了“全文完”这三个字,邮递员会不会在信件中间就误以为信已经读完了,从而把后面的内容丢弃呢?

计算机网络也面临着同样的问题。

PPP协议使用一个特殊的字节——标志字节 0x7E(二进制为 01111110)——来作为一帧的开始和结束。这就像我们例子中的“全文完”标记。

现在问题来了:PPP需要承载来自网络层的数据(比如一个IP数据报),我们称之为“数据载荷”(Payload)。这个数据载荷的内容是任意的,完全可能在数据的某个位置,也恰好出现了 0x7E 这个字节。

如果PPP协议对此不做任何处理,那么当接收方在数据中间读到 0x7E 时,就会错误地认为这一帧已经结束了,从而导致数据传输错误。

“透明传输” 指的就是,无论上层传来怎样的数据,数据链路层都应该能将其原封不动地传送过去,就像数据链路层是“透明”的一样。为了实现这一点,PPP必须有办法区分“作为数据的 0x7E”和“作为帧定界符的 0x7E”。

二、 PPP的解决方案:字节填充(Byte Stuffing)

PPP的解决方案非常巧妙,它引入了一个“魔法”——转义字符 0x7D(二进制为 01111101)。它的核心思想是:在发送数据前,对整个数据载荷进行一次扫描,如果遇到特殊的冲突字符,就用一个或多个字节的“转义序列”来替换它。

发送方(填充/转义)规则:

  1. 处理标志字节 0x7E:将数据载荷中出现的每一个 0x7E 字节,替换成一个由2字节组成的序列 (0x7D, 0x5E)

  2. 处理转义字节 0x7D:如果数据载荷中本身就包含了转义字符 0x7D,那么也需要对它进行转义。方法是将其替换为2字节序列 (0x7D, 0x5D)

考点深挖:这个替换规则是怎么来的?

你可能会想,0x5E 和 0x5D 是怎么选出来的?其实它们是原字节与 0x20(二进制 00100000)进行**异或(XOR)**运算的结果。

三、 实例演练:发送方的填充过程

假设网络层传来一段原始数据载荷为: 0x41 0x7E 0x42 0x7D 0x43。现在,作为发送方,我们需要对它进行字节填充。

  1. 0x41:是普通数据,保持不变。

  2. 0x7E:是标志字节,触发规则1,替换为 (0x7D, 0x5E)

  3. 0x42:是普通数据,保持不变。

  4. 0x7D:是转义字节,触发规则2,替换为 (0x7D, 0x5D)

  5. 0x43:是普通数据,保持不变。

处理完成后,将要实际发送的数据载荷变成了:0x41 0x7D 0x5E 0x42 0x7D 0x5D 0x43

这个新的序列被封装在两个 0x7E 标志字节之间,发送到链路上。接收方收到的就是这个填充后的序列,它内部绝不会再出现单个的 0x7E0x7D 字节了,从而实现了透明传输。

四、 逆向工程:接收方的解填充过程

当接收方收到数据后,需要执行填充的逆过程——解填充(Unstuffing),以恢复出原始数据。

接收方(解填充/去转义)规则:

接收方从左到右扫描收到的数据载荷:

  1. 如果读到的字节不是转义字符 0x7D,说明它就是原始数据,直接接收。

  2. 如果读到的字节转义字符 0x7D,那么说明后面紧跟着一个被转义的字节。此时,丢弃这个 0x7D,然后读取下一个字节,并将其与 0x20 进行异或(XOR),运算结果就是原始字节。

五、 实例演练:接收方的还原过程

现在,我们是接收方,收到了刚刚填充后的数据:0x41 0x7D 0x5E 0x42 0x7D 0x5D 0x43

  1. 0x41:不是 0x7D,是原始数据。还原出 0x41

  2. 0x7D:是转义字符,丢弃它,看下一个字节 0x5E。计算 0x5E XOR 0x20,得到 0x7E还原出 0x7E

  3. 0x42:不是 0x7D,是原始数据。还原出 0x42

  4. 0x7D:是转义字符,丢弃它,看下一个字节 0x5D。计算 0x5D XOR 0x20,得到 0x7D还原出 0x7D

  5. 0x43:不是 0x7D,是原始数据。还原出 0x43

最终,接收方成功将数据还原为:0x41 0x7E 0x42 0x7D 0x43,与发送前的原始数据完全一致!解填充成功。