CSMA/CD与CSMA/CA协议仿真:从退避算法到隐藏终端

发布时间:2026/10/17 12:27:38
CSMA/CD与CSMA/CA协议仿真:从退避算法到隐藏终端 简介这份MATLAB仿真源码面向通信与计算机网络方向的学习者和研究者用于对比理解CSMA/CA与CSMA/CD两种介质访问控制协议的工作机制。资源包共16个文件全部为.m脚本压缩包约17KB涵盖信道监听、冲突避免、冲突检测、退避时间设置、节点增减与帧收发记录等模块结构紧凑便于逐文件研读。已有6660人学习下载说明其在协议仿真入门中具有较高的参考价值。源码带有详细注释读者可据此复现无线局域网中预约信道、前导信号与确认接收等冲突避免流程也能观察以太网中碰撞检测与随机重试的完整逻辑并通过调整节点数量与参数、结合图形化输出直观比较两种协议在不同网络负载下的效率差异适合作为课程实验、自学演练与协议对比分析的实践素材。1. 为什么你的网络一忙就“装死”从 CSMA 家族的退避玄学说起你有没有遇到过这种场景宿舍里几个人同时开黑明明信号满格延迟却突然飙到几百毫秒技能按下去半天才响应。很多人第一反应是“路由器不行了”但真正在背后捣鬼的往往是一套看不见的规则——介质访问控制协议。以太网和 Wi-Fi 虽然都姓“CSMA”骨子里却是两套完全不同的性格一个叫 CSMA/CD一个叫 CSMA/CA。它们决定了多台设备抢一根“网线”或一段“空气”时谁先说话、撞车了怎么办、要不要提前打招呼。搞懂这两个协议的底层机制你就能明白为什么有线打游戏稳如老狗无线却时不时抽风。这份 MATLAB 仿真源代码带详细注释正好把这两个协议从数学公式变成了可以跑、可以改、可以看波形的实验台。接下来我会拆开讲冲突检测和冲突避免到底差在哪退避算法为什么是指数增长以及代码里那些看似随机的数字背后藏着什么设计取舍。2. CSMA/CD先听后说撞了再喊的“野蛮”哲学2.1 载波监听与冲突检测的时序逻辑CSMA/CD 的核心思想特别像一群人在一个没有主持人的会议室里发言。你想说话之前先听听有没有人在讲——这就是载波监听。如果安静你就开口如果有人在讲你就等。但问题来了两个人可能同时听到安静然后同时开口结果声音撞在一起。这时候 CSMA/CD 的第二个机制登场冲突检测。发送方在说话的同时还在听一旦发现自己发出的信号和别人撞了立刻停止发送并发出一个干扰信号相当于大喊一声“撞车了都别说了”。这个“边发边听”的能力要求收发器能同时进行发送和接收这也是为什么早期以太网用同轴电缆时冲突检测是可行的——信号会沿着总线传播回来。在 MATLAB 仿真里这个时序被离散化成一个个时隙。代码通常会维护一个状态变量表示当前信道是“空闲”“传输中”还是“冲突中”。每个节点在每个时隙开始时检查信道状态如果空闲且自己有帧要发就进入传输状态。传输过程中代码会模拟一个冲突窗口如果另一个节点也在同一时隙开始传输就标记为冲突。冲突发生后节点不是立刻重试而是进入退避状态。这个退避时间的计算就是二进制指数退避算法。% 二进制指数退避算法片段带注释 function backoff_time binary_backoff(collision_count, slot_time) % collision_count: 当前帧已经经历的冲突次数 % slot_time: 一个时隙的长度 % 退避窗口 2^min(collision_count, 10) - 1 % 最多退避 10 次后窗口不再翻倍防止无限增长 max_backoff min(collision_count, 10); window_size 2^max_backoff - 1; % 在 [0, window_size] 中随机选一个整数作为退避时隙数 backoff_slots randi([0, window_size]); backoff_time backoff_slots * slot_time; end这段代码的关键在于min(collision_count, 10)。为什么是 10因为如果冲突次数无限增长退避窗口会指数爆炸导致网络吞吐量骤降。以太网标准里规定当冲突次数达到 10 次后退避窗口就固定在 1023 个时隙不再翻倍。第 16 次冲突后帧会被丢弃上层协议负责重传。这个设计取舍很微妙窗口太小冲突概率高窗口太大信道利用率低。仿真代码里通常会统计不同冲突次数下的平均退避时隙数你能直观看到指数增长带来的“惩罚”效果。2.2 冲突窗口与最小帧长的隐藏约束CSMA/CD 有一个容易被忽略的硬性约束最小帧长。为什么以太网帧不能太短因为发送方必须在发送完整个帧之前检测到冲突。如果帧太短发送完了冲突信号还没传回来发送方就会误以为发送成功。这个时间窗口等于信号在总线上往返一次的时间也就是 2 倍的端到端传播延迟。在 10Mbps 以太网里这个往返时间大约是 51.2 微秒对应 64 字节的最小帧长。仿真代码里如果帧长设置得比这个值小你会看到冲突检测失效节点误判为成功发送但接收方收到的却是残缺数据。在 MATLAB 里模拟这个约束通常需要设置一个propagation_delay参数表示信号从总线一端传到另一端的时间。然后计算min_frame_time 2 * propagation_delay。如果帧的传输时间小于这个值仿真就会标记为“冲突未检测到”。这个细节在写仿真时特别容易翻车因为很多人只关注退避算法忘了物理层的时间约束。我一般会在代码里加一个断言检查帧长是否满足最小帧长要求否则直接报错避免跑出一堆看似正常但物理上不可能的结果。2.3 仿真中的吞吐量计算与状态机实现CSMA/CD 仿真的核心是一个状态机每个节点在“空闲”“等待”“传输”“退避”“成功”“失败”这几个状态之间切换。MATLAB 代码通常用switch-case或者if-else来实现状态转移。吞吐量的计算方式是统计一段时间内成功传输的帧数乘以帧长再除以总仿真时间。但这里有个坑仿真时间不能太短否则随机性太大也不能太长否则跑得慢。一般会跑 1000 个帧周期以上取平均值。代码里还会维护一个collision_count数组记录每个节点经历的冲突次数。你可以画出冲突次数随时间的分布图会看到大多数帧第一次就成功少数帧经历多次冲突。这个分布近似几何分布但尾部被截断了。另一个值得关注的指标是信道利用率。在负载较轻时CSMA/CD 的利用率可以接近 1但当负载超过 0.5 左右时冲突急剧增加利用率反而下降。这个拐点就是 CSMA/CD 的“性能悬崖”。仿真代码里可以通过调整节点数量和帧到达率复现这个悬崖曲线。3. CSMA/CA为什么 Wi-Fi 不能“边发边听”3.1 隐藏终端与暴露终端无线世界的两难CSMA/CA 和 CSMA/CD 最大的区别在于无线环境里发送方无法在发送的同时监听信道。因为发送的信号强度远大于接收到的信号自己的信号会把别人的信号淹没。这就导致 CSMA/CD 的冲突检测机制在无线里直接失效。更麻烦的是无线网络存在“隐藏终端”问题节点 A 和节点 C 都能和节点 B 通信但 A 和 C 互相听不到。如果 A 和 C 同时向 B 发送就会在 B 处冲突但 A 和 C 都以为信道空闲。另一个问题是“暴露终端”节点 B 正在向 A 发送节点 C 听到了 B 的信号于是推迟发送但实际上 C 向 D 发送并不会干扰 B 到 A 的通信。这两个问题让无线介质访问变得异常复杂。CSMA/CA 的解决思路是“避免”而不是“检测”。既然不能边发边听那就尽量在发送前确保不会冲突。具体做法包括帧间间隔、竞争窗口、确认帧。发送方在发送数据之前先等待一个帧间间隔然后进入退避过程。退避计数器只在信道空闲时递减一旦信道变忙就冻结。当计数器减到零才发送数据。接收方收到数据后等待一个短帧间间隔然后回复一个确认帧。如果发送方没收到确认就认为发生了冲突加倍竞争窗口重新退避。这个机制本质上是用“握手”来替代“监听”。3.2 退避计数器与帧间间隔的协同机制CSMA/CA 的退避计数器和 CSMA/CD 的退避时间有一个关键区别CSMA/CD 的退避是冲突发生后的“惩罚”而 CSMA/CA 的退避是发送前的“预防”。在 CSMA/CA 里即使信道空闲节点也要先退避一段时间只是这个退避时间可能为零。退避计数器在每个时隙递减时隙的长度取决于物理层。如果信道在某个时隙变忙计数器就暂停等信道再次空闲并经过一个帧间间隔后继续递减。这个“冻结”机制保证了多个节点不会同时把计数器减到零。帧间间隔分为几种短帧间间隔用于高优先级帧比如确认帧分布式协调功能帧间间隔用于普通数据帧点协调功能帧间间隔用于轮询。优先级越高的帧等待的间隔越短越容易抢到信道。仿真代码里这些间隔通常用不同的常数表示比如SIFS 10e-6DIFS 50e-6。退避时隙slot_time一般等于SIFS加上传播延迟和处理延迟。代码里会有一个循环每个时隙检查信道状态如果空闲且退避计数器大于零就减一如果减到零就发送。% CSMA/CA 退避计数器递减逻辑带注释 function [backoff_counter, can_transmit] ca_backoff_step(backoff_counter, channel_busy, slot_time) % backoff_counter: 当前退避计数器的值单位时隙 % channel_busy: 当前时隙信道是否忙 % slot_time: 一个时隙的持续时间 can_transmit false; if channel_busy % 信道忙计数器冻结不递减 return; end if backoff_counter 0 % 信道空闲计数器减一 backoff_counter backoff_counter - 1; end if backoff_counter 0 % 计数器归零可以发送 can_transmit true; end end这段代码里channel_busy的判断非常关键。在仿真中信道忙可能因为别的节点正在发送也可能因为别的节点正在等待帧间间隔。如果判断逻辑写错比如把帧间间隔也算作忙退避计数器就会一直冻结导致节点永远发不出去。常见的实现思路是用一个全局变量记录信道的“忙闲”状态每个时隙更新一次。更新时先检查是否有节点正在传输再检查是否有节点处于帧间间隔。只有两者都不满足信道才算空闲。3.3 RTS/CTS 握手用带宽换稳定的取舍CSMA/CA 还有一个可选机制RTS/CTS 握手。发送方先发一个请求发送帧接收方回复一个清除发送帧然后发送方才发数据。这个机制专门解决隐藏终端问题即使 A 和 C 互相听不到它们都能听到 B 发出的 CTS从而知道 B 即将被占用。但 RTS/CTS 也有代价每次传输都要多两个控制帧增加了开销。对于短帧这个开销可能比冲突造成的损失还大。所以实际网络里RTS/CTS 通常只对超过某个阈值的帧启用。在 MATLAB 仿真里RTS/CTS 的实现需要增加两个状态等待 CTS 和等待数据。发送方发出 RTS 后启动一个超时定时器。如果超时前收到 CTS就发送数据否则认为 RTS 冲突加倍退避窗口。接收方收到 RTS 后等待一个 SIFS然后回复 CTS。其他节点听到 CTS 后会更新自己的网络分配向量在 NAV 指定的时间内保持沉默。NAV 是一个定时器相当于“预约”了信道。仿真代码里NAV 通常用一个数组表示每个节点维护自己的 NAV 值。当节点收到 RTS 或 CTS 时根据帧里的持续时间字段更新 NAV。NAV 大于零时节点即使听到信道空闲也不能发送。这个机制的设计取舍很明显RTS/CTS 提高了可靠性但降低了效率。仿真代码里可以通过开关变量控制是否启用 RTS/CTS然后对比两种模式下的吞吐量和冲突率。你会看到在节点数量多、帧长较长时RTS/CTS 明显占优而在节点少、帧短时不启用反而更快。这个对比实验是理解 CSMA/CA 设计精髓的最好方式。4. 避坑与排查仿真跑不通时先看这几个地方4.1 冲突检测失效帧长小于最小帧长现象仿真结果显示很多帧“成功发送”但接收方收到的数据是乱的或者冲突计数为零但吞吐量异常高。原因帧的传输时间小于 2 倍的传播延迟发送方在冲突信号返回之前就发完了误判为成功。解决检查代码里的frame_length和propagation_delay确保frame_length / data_rate 2 * propagation_delay。如果不满足要么加长帧要么减小传播延迟。在以太网仿真里最小帧长通常设为 64 字节传播延迟设为 25.6 微秒对应 10Mbps 和 2.5km 电缆。4.2 退避计数器不递减信道忙闲判断错误现象节点一直处于退避状态退避计数器永远不归零吞吐量为零。原因信道忙闲判断逻辑把帧间间隔也算作“忙”导致退避计数器在每个时隙都被冻结。解决检查channel_busy的计算逻辑。正确的做法是先判断是否有节点正在传输数据或控制帧再判断是否有节点处于帧间间隔。只有两者都不满足信道才算空闲。另外注意帧间间隔的类型SIFS 期间信道是忙的但 DIFS 期间如果没有任何传输信道应该算空闲。4.3 隐藏终端导致持续冲突NAV 未生效现象启用了 RTS/CTS但冲突率依然很高吞吐量没有改善。原因NAV 更新逻辑有误其他节点没有正确设置 NAV或者 NAV 在帧间间隔期间被错误清零。解决检查收到 RTS 或 CTS 后是否正确提取了持续时间字段并更新了本地 NAV。NAV 应该只在收到新的 RTS/CTS 时更新且取最大值。另外NAV 递减应该在每个时隙进行而不是在信道空闲时。如果 NAV 递减逻辑写错节点可能会在 NAV 未归零时提前发送导致冲突。4.4 吞吐量曲线异常仿真时间太短或随机种子固定现象吞吐量随负载变化的曲线不平滑或者每次运行结果差异很大。原因仿真时间太短随机事件没有充分平均或者随机种子固定导致每次运行相同的序列。解决增加仿真帧数至少 1000 个帧周期以上。同时每次运行前用rng(shuffle)重置随机种子确保结果具有统计意义。如果曲线仍然抖动可以多次运行取平均值。另外注意负载的定义负载通常指所有节点产生的帧的总到达率而不是单个节点的到达率。4.5 状态机死锁节点卡在某个状态无法转移现象仿真运行到一半停止某个节点一直处于“等待确认”或“退避”状态不再变化。原因状态转移条件不完整比如等待确认的超时定时器没有递减或者退避计数器在信道持续忙时永远冻结。解决检查每个状态的超时机制。等待确认应该有超时定时器超时后回到退避状态。退避状态应该有最大退避次数限制超过后丢弃帧并回到空闲。另外确保每个时隙所有节点的状态都更新一次避免遗漏。5. 从仿真到真实网络参数调优背后的设计取舍仿真跑通之后最有价值的部分是调参。你会发现CSMA/CD 和 CSMA/CA 的性能对参数极其敏感。比如 CSMA/CD 的退避窗口上限设成 1023 和设成 255在高负载下的吞吐量能差一倍。CSMA/CA 的帧间间隔SIFS 和 DIFS 的差值直接决定了确认帧能不能抢在数据帧之前发送。这些参数在标准里都是经过大量仿真和实测才定下来的不是拍脑袋想的。我一般会做一组对比实验固定节点数量从 2 个增加到 50 个观察吞吐量和平均延迟的变化。CSMA/CD 在节点数超过 20 左右时吞吐量开始明显下降因为冲突概率随节点数增加而急剧上升。CSMA/CA 在节点数增加时吞吐量下降更平缓因为退避机制和 RTS/CTS 能更好地分散竞争。但 CSMA/CA 的延迟更高因为每次发送前都要等待帧间间隔和退避。这个延迟和吞吐量的权衡就是无线网络设计的核心矛盾。另一个值得深挖的点是捕获效应。在无线环境里如果两个节点同时发送信号强的那个可能被接收方正确解码信号弱的则被丢弃。这个效应在仿真里可以通过设置不同的发射功率来模拟。捕获效应会改变冲突的概率分布让某些节点更容易成功。实际网络里这会导致公平性问题离接入点近的节点吞吐量高远的节点经常被“饿死”。CSMA/CA 的退避机制在一定程度上缓解了这个问题但无法完全消除。从那以后我每次调无线参数都会先跑一遍仿真看看捕获效应和隐藏终端的影响有多大再决定 RTS/CTS 阈值和退避窗口怎么设。这份 MATLAB 源代码把所有这些机制都拆成了可修改的函数和参数你可以直接改数字、看波形、对比结果。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询