我不是专业的 Wi-Fi 技术工作者。但我可以谈谈作为统计复用网络的 Wi-Fi,通用的网络分布式协调功能在底层是相通的。
从一个图展开:
基于这底层逻辑,共享以太网可以用 CSMA/CD,而 Wi-Fi 只能用 CSMA/CA,区别在 CD(冲突检测) 和 CA(冲突避免)。
以太网做冲突检测很简单,直观讲,假设把信号电压约束在 0~5V,只要检测到大于 5 + δV 电压就意味着冲突,但 Wi-Fi 就没这么简单,于是隐藏节点和暴露节点问题被拎出来。
在调查评估这些问题事实上有多大影响,需不需要花大力气解决之前,工人的思路往往是先解决它们。因为无法 CD,则只能 CA。从另一个更合理的角度看,如果不能 CD,最简单的方法应只保留 CSMA,而不是解决不能 CD 的问题。没有了 CD,Wi-Fi 的 MAC 逻辑变得更加简洁:直接随机二进制退避发送,直到成功或彻底失败。
但这种极简的 MAC 逻辑会带来比较大的冲突概率,显然无法满足性能需求,那么接下来的起点应从物理层入手,从此步入正轨。但即使 802.11 也有犯糊涂的时候,产出了 RTS/CTS 这种复杂但没卵用的设计。同样的故事在 TCP 演进过程中经常发生,降低物理层误码率,很多拥塞控制层面复杂的丢包检测机制和算法就不再需要。在物理层尚未做出改变前,等待好于折腾。典型的本末倒置设计一般都是希望其外的金玉掩盖其中的败絮开始。
回到上图,信号特征的区别是有线无线网络的最本质区别,RTS/CTS 的思路也简单,见招拆招,既然信号在接收端看起来比较拉,就从 receiver 而不是 sender 入手来检测或避免冲突,流程就顺理成章了。
但欲发送数据帧的 sender 根本不知道 receiver 的情况,既不知道距离多远,也不知道 receiver 附近是否有自己检测不到的其它传输正在发生,唯一能做的就是低成本询问。由于共享介质特征,询问结果至少需要保留一帧成功接收的时间,这次询问才有意义,于是询问必须带有 “资源预留” 的含义:
- sender 附近的节点均可收到信号强度不弱的 RTS,获知了 sender 的资源预留申请;
- receiver 如果能收到 RTS 并回复 CTS,CTS 足够强到让其附近节点收到,它们也获知 sender 的资源申请;
- CTS 回到 sender,sender 开始发送帧;
- receiver 如果收不到 RTS,sender 将超时重试发送 RTS;
这样一来,sender,receiver 附近的所有相关节点都知道了 sender 将有帧要发往 receiver,并主动避让,避让时间包含在 RTS,CTS 帧头字段中,大约为 sender 成功发帧的时间。这一切看起来就是这么顺理成章。
理论上,RTS 中应该包含两个 “避让时间”,一个是 sender 附近节点需要避让的时间 D1,另一个是 receiver 附近节点需要避让的时间 D2,由 receiver 在 CTS 中 echo 回来被其附近节点收到,D1 < D2。原因也不难理解,D1 只是 RTS/CTS 这种短帧来回的时间,而 D2 才是长数据帧来回的时间。如果 sender 的 RTS 有去无回,附近其它节点就可以竞争信道,回避 D2 的时间就没有必要。
更进一步,D1 甚至可以是 0,只要 sender 附近节点听不到 receiver 发送的 CTS,它们就可以自由和其它节点通信,从而解决暴露节点问题。但 802.11 只是简单的全部避让。
看起来很不错的一个机制,但仔细琢磨,它只是在小心翼翼避免根本避免不了或根本不会发生的问题:
- 如果 sender 要发送的数据帧很短,何不直接发送(或者包在 RTS/CTS 中)呢;
- AP 对任何节点均可达,AP 根本没有隐藏站,暴露站问题;
- 虽然 RTS/CTS 相比数据帧很小,在越来越大的带宽下,二者影响越来越一致;
- 隐藏站和暴露站并不多见…
如果不能精确认领和解决问题,在弹性系统中交给概率是最好方法。RTS/CTS 机制非常类似 TCP 的 D-SACK,对大多数场景帮助不大,少数可以帮助到的场景,获得的全局收益不大。它也非常像人们集中大量时间和精力优化异常流的做法,比如优化 TCP 丢包检查和重传,却只为解决非常罕见的问题。
同样都是 “链路资源预留”,电路交换就是精确认领解决问题,仔细品它们的区别。类似的经验在数据中心正在融合,还是那个观点,网络越往高速发展,就越不可抗拒地将设计推回到面向连接的电路交换,同时代价也是昂贵的,但作为非汇聚非骨干的普通接入网络,高速和通用兼容需要权衡轻重,这一点上,Wi-Fi,TCP,接入以太网有相似的特征,它们成功的原因一致,也踩过同样的坑。
浙江温州皮鞋湿,下雨进水不会胖。