1. 认识 HDLC
HDLC(High-Level Data Link Control,高级数据链路控制)是一种面向比特的同步数据链路层协议,是数据链路层的一种具体实现。
注:「面向比特」是指该协议以比特为单位组织数据,不依赖特定字符编码;帧的起止和字段边界通过特殊比特序列界定,而非依赖字符(如'EOF')。
HDLC 定义了如何成帧、如何差错控制、如何流量控制以及如何管理链路等机制,适用同步串行链路、卫星通信、点对点专线等场景。
2. 所属网络层级
HDLC 工作在 OSI 参考模型中的第二层------数据链路层(Data Link Layer)。
| 层级 | 名称 | HDLC 的位置与职责 |
|---|---|---|
| 第 3 层 | 网络层 | 路由寻址 |
| 第 2 层 | 数据链路层 | HDLC 在此层:成帧、差错检测、流量控制、链路管理 |
| 第 1 层 | 物理层 | 比特流在物理介质上的传输 |
数据链路层向上(网络层)提供透明的帧传输服务,向下(物理层)把帧转换为比特流。HDLC 在该层主要解决三个基本问题:
- 封装成帧:在网络层交付的数据前后加上首部和尾部,组成完整帧。
- 透明传输:通过比特填充等技术,保证数据中的任意比特组合都能正确传输。
- 差错检测:通过帧校验序列(FCS)检测传输中出现的比特错误。
3. HDLC 的作用
HDLC 的核心作用可以归纳为以下几点:
3.1 成帧与透明传输
HDLC 使用特殊的标志序列(Flag)来界定帧的开始与结束,并通过 零比特插入/删除 机制实现透明传输,保证数据字段中即使出现与标志相同的比特序列,也不会被误判为帧边界。
3.2 差错检测与重传
每帧携带 FCS(Frame Check Sequence,帧校验序列),接收方通过校验判定帧是否出错。配合序号(N(S)、N®)可以实现出错重传,保证数据的可靠性(在采用可靠模式时)。
3.3 流量控制
通过接收序号 N® 进行捎带确认,接收方告知发送方自己期望接收的下一帧序号,从而间接控制发送窗口,防止发送方过快发送而淹没接收方。
3.4 链路管理
HDLC 定义了多种帧类型(信息帧、监督帧、无编号帧),可以完成链路的建立、维护、重置与释放,支持点对点和多点链路。
3.5 对上层协议的统一承载
HDLC 作为一种通用数据链路层封装,可以承载上层多种网络层协议。在实际网络中,Cisco 设备串行链路默认封装的 HDLC 与标准略有差异,但整体思想一致。
4. HDLC 帧格式
一个标准的 HDLC 帧由以下字段组成:
+----------+----------+-----------+----------+----------+----------+
| Flag | Address | Control | Data | FCS | Flag |
| 8 bit | 8 bit* | 8/16 bit | 可变 | 16/32 bit| 8 bit |
+----------+----------+-----------+----------+----------+----------+
4.1 Flag 字段
- 值固定为
01111110(0x7E)。 - 连续两个 Flag 之间的内容构成一个帧的主体。
- 为保证数据中不出现
01111110造成误判,发送方采用零比特填充:
发送端:在发送 Flag 之外的数据时,连续遇到 5 个连续的 1 后自动插入一个 0 。
接收端:在收到数据时,连续遇到 5 个连续的 1 后自动删除其后的一个 0。
例如,原始比特流中若出现 1111101,发送方会将其变为 11111001,接收方再恢复为 1111101,从而避免数据中出现与 Flag 相同的比特模式。
4.2 Address 字段
理论上需要规划,标识对端站点,但现网基本不需要。
- 标识帧的接收地址。
- 标准 HDLC 中为 8 bit(可扩展为多个字节,扩展时最低位为 0 表示后续还有地址字节)。
- 在点对点链路中,实际效果弱化,可填
0xFF表示广播;在多点链路中用于区分不同站点。
4.3 Control 字段
Control 字段决定了帧的类型。HDLC 定义了三种帧类型:信息帧(I 帧)、监督帧(S 帧)、无编号帧(U 帧)。
4.3.1 8 bit 控制字段的三种格式
信息帧(I 帧):用于承载数据,首比特为 0。
bit: 7 6 5 4 3 2 1 0
| 0 | N(S) | P/F | N(R) |
N(S):发送序号,标识当前发送帧的编号(3 bit,可表示 0~7)。N(R):接收序号,捎带确认,表示期望接收的下一个帧的序号。P/F:Poll/Final 位,用于查询或终止响应。
监督帧(S 帧) :接收方回复的响应,用于差错控制和流量控制,首两比特为 10。
bit: 7 6 5 4 3 2 1 0
| 1 | 0 | S | P/F | N(R) |
S字段(2 bit)决定具体类型:00= RR(Receive Ready,接收就绪,确认且可继续接收)。10= RNR(Receive Not Ready,接收未就绪,暂停发送)。01= REJ(Reject,拒绝,请求重发 N® 起的所有帧)。11= SREJ(Selective Reject,选择拒绝,请求重发指定帧)。
N(R):与 I 帧中的 N® 一样,用于确认和流量控制。
无编号帧(U 帧) :用于链路建立、断开及管理等,首两比特为 11。
bit: 7 6 5 4 3 2 1 0
| 1 | 1 | M1 | P/F | M2 |
M1、M2编码决定具体命令:- SABM(Set Asynchronous Balanced Mode):建立异步平衡模式连接。
- UA(Unnumbered Acknowledge):无编号确认。
- DISC(Disconnect):断开连接。
- DM(Disconnected Mode):拒绝建链 / 我还在断开状态。
- FRMR(Frame Reject):帧拒绝,指示收到无效帧。
4.3.2 P/F 位的作用
- 在命令帧中称为 P 位(Poll),用于查询对方状态;
- 在响应帧中称为 F 位(Final),表示对该查询的最终响应。
主要用于以下场景:
- 查询对端是否响应
主站发送 P=1 的命令帧,就是在问:"你现在状态如何?请回复我。"对端收到后,要用 F=1 的响应帧回答。 - 控制谁可以发送
在 NRM 正常响应方式下,从站必须被主站轮询后才能发送。主站置 P=1,相当于把发送权交给从站;从站发完最后一帧时置 F=1,表示交回控制权。 - 强制对方回一个确认
在 ARM/ABM 方式下,从站本来就可以主动发送,但主站仍可用 P=1 强制对方立即返回一个带 F=1 的响应帧。 - 做 Checkpoint,同步序号状态
如果长时间没收到确认,发送方可以发一个 P=1 的帧;对方回一个 F=1 的帧,并在N(R)里告诉发送方"我下一个期望收到几号帧"。这样双方就能重新对齐发送/接收序号,发现丢失帧并重传。
4.4 Data 字段
- 长度可变,承载上层数据。
- 在 I 帧中通常必有 Data 字段;S 帧和部分 U 帧可以没有 Data 字段。
- 数据内容受零比特填充机制保护,实现透明传输。
4.5 FCS 字段
- 采用循环冗余校验(CRC)生成,用于检测帧在传输过程中的比特错误。
- 通常为 16 bit,使用 CRC-CCITT 多项式;某些实现中可扩展为 32 bit。
- 发送方对 Address 到 Data 字段(不含 Flag)进行计算,接收方用同样方式校验,若结果不符则丢弃该帧并依据配置要求重传。
5. 详细交互步骤举例
假设两个站点 A 和 B 通过同步串行链路通信,采用 HDLC 的异步平衡模式(ABM)。下面分阶段说明交互过程。
5.1 链路建立阶段
A B
|------ SABM (P=1) -------->|
|<------ UA (F=1) ----------|
- A 发起连接 :A 向 B 发送一个 U 帧
SABM(P 位置 1),请求建立异步平衡模式连接。 - B 响应确认 :B 收到后,回复 U 帧
UA(F 位置 1),表示同意建立连接。 - 链路进入可传输数据的状态,双方初始化发送序号和接收序号。
5.2 数据传输阶段
A B
|--- I 帧 N(S)=0, N(R)=0 --------->|
|<-- I 帧 N(S)=0, N(R)=1 ---------| (捎带确认 0 号帧)
|--- I 帧 N(S)=1, N(R)=1 --------->|
|<-- RR 帧 N(R)=2 ----------------| (确认已收到 1 号帧)
建立连接后,A 与 B 通过 I 帧交换数据,并使用 N(S)、N® 进行确认。
- A 发送 I 帧
N(S)=0, N(R)=0给 B,携带数据 Data1。 - B 成功接收后,可发送 I 帧
N(S)=0, N(R)=1,其中N(R)=1表示期望接收 A 的下一个帧序号为 1,同时捎带确认已正确收到 0 号帧。 - A 收到确认后,继续发送 I 帧
N(S)=1, N(R)=1,携带数据 Data2。 - 若 A 没有新的数据要发送,可发送监督帧 RR
N(R)=期望值单独确认。
5.3 差错与流量控制阶段
假设传输过程中发生如下情况:
A B
|--- I 帧 N(S)=2 ----------------->| (正确接收)
|--- I 帧 N(S)=3 ----------------->| (校验失败丢弃)
|<-- REJ 帧 N(R)=3 ---------------|
|--- I 帧 N(S)=3 ----------------->| (重发)
- A 连续发送 N(S)=2、N(S)=3 两帧,但 B 只正确收到 N(S)=2,N(S)=3 校验失败被丢弃。
- B 发送 REJ 帧
N(R)=3,要求 A 从 3 号帧开始重发。 - A 收到 REJ 后,重新发送 N(S)=3 及其后的所有帧。
另外,当 B 的接收缓冲区不足时,可发送 RNR 帧 N(R)=期望值 通知 A 暂停发送;待可以接收时再发送 RR 帧通知恢复。
5.4 断开阶段
传输完成后,任一方可发起断开:
A B
|------ DISC (P=1) -------->|
|<------ UA (F=1) ----------|
- A 向 B 发送 U 帧
DISC(P 位置 1),请求断开连接。 - B 回复 U 帧
UA(F 位置 1),表示确认断开。 - 双方停止数据传输,链路断开。
6. 滑动窗口
HDLC 为提高链路利用率,允许发送方在收到确认前连续发出多个 I 帧,这就是滑动窗口机制。N(S) 和 N(R) 正是驱动窗口移动的两个关键序号。
6.2 滑动窗口是什么样的窗口
可以把它想象成一个只能装下固定数量帧号的"框":
- 发送窗口 W_S:窗口内的帧号是当前允许发送的;窗口下沿是下一个待确认的帧号,窗口上沿是还能继续发送的最大帧号。
- 接收窗口 W_R :HDLC 按序接收,通常只接受"正好等于当前期望序号
N(R)"的帧,序号不符的帧会被丢弃。 N(R),N(S)都是4位,窗口大小最大表示为8
每收到一个确认 N(R),A 就把窗口下沿滑动到 N(R) 的位置。序号到达 7 之后再回到 0,形成闭环。
6.3 完整举例:窗口大小 3,模 8
假设 A 要连续发送 Data1~Data5,分别编号 N(S)=0、1、2、3、4;B 只接收不主动发数据,用 RR 帧确认。
"站点 B(接收方)" "站点 A(发送方)" "站点 B(接收方)" "站点 A(发送方)" #mermaid-svg-eexEBuBnluQT2rcU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eexEBuBnluQT2rcU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eexEBuBnluQT2rcU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eexEBuBnluQT2rcU .error-icon{fill:#552222;}#mermaid-svg-eexEBuBnluQT2rcU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eexEBuBnluQT2rcU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eexEBuBnluQT2rcU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eexEBuBnluQT2rcU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eexEBuBnluQT2rcU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eexEBuBnluQT2rcU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eexEBuBnluQT2rcU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eexEBuBnluQT2rcU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eexEBuBnluQT2rcU .marker.cross{stroke:#333333;}#mermaid-svg-eexEBuBnluQT2rcU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eexEBuBnluQT2rcU p{margin:0;}#mermaid-svg-eexEBuBnluQT2rcU .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eexEBuBnluQT2rcU text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-eexEBuBnluQT2rcU .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-eexEBuBnluQT2rcU .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-eexEBuBnluQT2rcU .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-eexEBuBnluQT2rcU .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-eexEBuBnluQT2rcU #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-eexEBuBnluQT2rcU .sequenceNumber{fill:white;}#mermaid-svg-eexEBuBnluQT2rcU #sequencenumber{fill:#333;}#mermaid-svg-eexEBuBnluQT2rcU #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-eexEBuBnluQT2rcU .messageText{fill:#333;stroke:none;}#mermaid-svg-eexEBuBnluQT2rcU .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eexEBuBnluQT2rcU .labelText,#mermaid-svg-eexEBuBnluQT2rcU .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-eexEBuBnluQT2rcU .loopText,#mermaid-svg-eexEBuBnluQT2rcU .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-eexEBuBnluQT2rcU .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-eexEBuBnluQT2rcU .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-eexEBuBnluQT2rcU .noteText,#mermaid-svg-eexEBuBnluQT2rcU .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-eexEBuBnluQT2rcU .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eexEBuBnluQT2rcU .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eexEBuBnluQT2rcU .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-eexEBuBnluQT2rcU .actorPopupMenu{position:absolute;}#mermaid-svg-eexEBuBnluQT2rcU .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-eexEBuBnluQT2rcU .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-eexEBuBnluQT2rcU .actor-man circle,#mermaid-svg-eexEBuBnluQT2rcU line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-eexEBuBnluQT2rcU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "窗口大小 k=3,序号 0~7 循环(模 8)" "B 回 N(R)=3 表示 0、1、2 全部确认" "I 帧 N(S)=0, N(R)=0(Data1)""I 帧 N(S)=1, N(R)=0(Data2)""I 帧 N(S)=2, N(R)=0(Data3),窗口满暂停发送""RR N(R)=1(已收到0,期望1)""I 帧 N(S)=3, N(R)=1(Data4)""RR N(R)=2(已收到1,期望2)""I 帧 N(S)=4, N(R)=2(Data5)""RR N(R)=3(已收到2,期望3)"
对应下来,A 侧的窗口变化如下:
| 阶段 | A 发送的内容 | B 返回的 N® | A 发送窗口下沿 | 还能继续发送的帧 |
|---|---|---|---|---|
| 初始 | --- | --- | 0 | N(S)=0、1、2 |
| 连发 3 帧 | N(S)=0、1、2 | --- | 0(等待确认) | 无,窗口已满 |
| 收到第 1 个确认 | --- | N®=1 | 1 | N(S)=3 |
| 收到第 2 个确认 | --- | N®=2 | 2 | N(S)=4 |
| 收到第 3 个确认 | --- | N®=3 | 3 | N(S)=5、6、7... |
从表中可以看到两个关键动作:
- N(S) 负责"编号":A 发出的每一帧都用 N(S) 标记自己在窗口中的位置,B 也据此判断该帧是不是自己当前想要的。
- N® 负责"放行":B 每回一个更大的 N®,A 的窗口下沿就向右移动,让出新的可发送帧号。A 由此知道哪些帧已被确认、可以继续发送,从而在不停止发送的情况下实现可靠传输与流量控制。
6.4 出错时窗口如何回退
结合 5.3 节的错误场景:假设窗口大小为 3,A 已经发出 N(S)=2、N(S)=3,其中 N(S)=2 正确到达,N(S)=3 校验失败被丢弃。
- B 正确收到 N(S)=2 后,返回 RR
N(R)=3,A 的窗口下沿滑到 3。 - 但 B 实际发现 3 号帧丢失,于是又回 REJ
N(R)=3,意思是从 3 号开始全部重发。 - A 收到
N(R)=3后,把窗口下沿重新对准 3,并从 N(S)=3 及其后续帧开始重发。
"站点 B(接收方)" "站点 A(发送方)" "站点 B(接收方)" "站点 A(发送方)" #mermaid-svg-HePy9iQ5kqsJykiz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HePy9iQ5kqsJykiz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HePy9iQ5kqsJykiz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HePy9iQ5kqsJykiz .error-icon{fill:#552222;}#mermaid-svg-HePy9iQ5kqsJykiz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HePy9iQ5kqsJykiz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HePy9iQ5kqsJykiz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HePy9iQ5kqsJykiz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HePy9iQ5kqsJykiz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HePy9iQ5kqsJykiz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HePy9iQ5kqsJykiz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HePy9iQ5kqsJykiz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HePy9iQ5kqsJykiz .marker.cross{stroke:#333333;}#mermaid-svg-HePy9iQ5kqsJykiz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HePy9iQ5kqsJykiz p{margin:0;}#mermaid-svg-HePy9iQ5kqsJykiz .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HePy9iQ5kqsJykiz text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-HePy9iQ5kqsJykiz .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-HePy9iQ5kqsJykiz .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-HePy9iQ5kqsJykiz .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-HePy9iQ5kqsJykiz .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-HePy9iQ5kqsJykiz #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-HePy9iQ5kqsJykiz .sequenceNumber{fill:white;}#mermaid-svg-HePy9iQ5kqsJykiz #sequencenumber{fill:#333;}#mermaid-svg-HePy9iQ5kqsJykiz #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-HePy9iQ5kqsJykiz .messageText{fill:#333;stroke:none;}#mermaid-svg-HePy9iQ5kqsJykiz .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HePy9iQ5kqsJykiz .labelText,#mermaid-svg-HePy9iQ5kqsJykiz .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-HePy9iQ5kqsJykiz .loopText,#mermaid-svg-HePy9iQ5kqsJykiz .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-HePy9iQ5kqsJykiz .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-HePy9iQ5kqsJykiz .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-HePy9iQ5kqsJykiz .noteText,#mermaid-svg-HePy9iQ5kqsJykiz .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-HePy9iQ5kqsJykiz .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HePy9iQ5kqsJykiz .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HePy9iQ5kqsJykiz .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HePy9iQ5kqsJykiz .actorPopupMenu{position:absolute;}#mermaid-svg-HePy9iQ5kqsJykiz .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-HePy9iQ5kqsJykiz .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HePy9iQ5kqsJykiz .actor-man circle,#mermaid-svg-HePy9iQ5kqsJykiz line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-HePy9iQ5kqsJykiz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "实际 3 号帧丢失" "I 帧 N(S)=2(正确收到)""I 帧 N(S)=3(丢失)""RR N(R)=3(确认已收到 2)""REJ N(R)=3(要求从 3 号重发)""I 帧 N(S)=3(重发)"
可见:确认帧与差错帧都通过 N(R)=3 这个值指挥发送方把窗口下沿放到 3,只是监督帧类型不同------RR 表示正常滑动,REJ 表示回退重传。若 B 缓冲区不足,则发 RNR N(R)=3,发送窗口暂时不滑动;等到可接收时再发 RR N(R)=3 继续放行。
7. 小结
HDLC 是数据链路层经典的面向比特协议,其核心机制包括:
- 用 Flag 界定帧边界,通过零比特填充实现透明传输;
- 用 FCS 实现差错检测;
- 用 Control 字段区分 I/S/U 帧,并携带 N(S)、N® 实现可靠传输与流量控制;
- 用 U 帧完成链路建立、断开等管理操作。