前言
- 个人邮箱:zhangyixu02@gmail.com
- 在学习 BLE 过程中,总能听到 “丢包” 一词,但是我查阅资料又发现,有大佬说,ATT所有命令都是“必达”的,不存在所谓的“丢包”。而且我发现,在宣传 BLE 产品时候,从来没有商家宣传过自己丢包率有多低,一般都是宣传的功耗和传输速率。
- 一顿操作下来,这彻彻底底把我这个菜鸟搞懵逼的了。为了搞明白这其中的概念,我查阅了各种资料,结合个人理解写一下我对 BLE 丢包这一词的概念。
- 如果有误,请大佬不吝赐教。
丢包的概念
个人认为,对于丢包这一词,我们应当站在不同的层级说不同的话,这样我们就能够真正的理解,为什么有些大佬说ATT所有命令都是“必达”的,不存在所谓的“丢包”。而又有一些大佬说,BLE 怎么可能不丢包。这**两种说法其实并没有错误,只是所站的角度不同
**,因此说出来的话看起来完全对立。
Control 层
丢包理解
- 在 Control 层是存在丢包行为的,因为电磁干扰、网络带宽不足、信号衰减、设备故障等物理因素导致数据包无法成功传递到对端设备。
- 因此,当发送数据给对端设备的 150us 后需要收到对端设备的 ACK 回应数据包。如果没有收到对端设备的 ACK,那么就会启动重传机制,一直等到对端设备发回的 ACK 命令,如果等待时间超过了监管超时时间那么就会进行断连。
- 对端设备在收到数据后,会进行 CRC 校验,确保数据在传输过程中没有因为各种物理因素导致接收到错误信息。
什么是 ACK
- 这个时候肯定会有人问,ACK 是啥玩意,怎么抓包没有抓取过,难道空包就是 ACK?如果你明白了 BLE LL 层数据包结构,就将会明白所谓的 ACK 是什么了。
- 首先我们先看一下 LL 层数据包格式,我们重点看 SN 和 NESN 这两位进行重传判断。
- 序列号(SN):当前主机发送的数据包序列。
- 下一个预期序列号(NFSN):从机期待收到下一个主机发来的数据包序列号。
- 现在我们来看看实例进一步理解。
- 主机发送数据报文,SN = 0,NESN = 0
- 从机此时收到数据报文后,期望下一包收到的数据包序列号为 0,因此 NESE = 1。而当前数据包是用于回复主机序列号为 0 的数据包的,因此,SN =0。
- 因为各种原因,一段时间内主机并没有收到从机回复包,因此进行数据重传。
- 从机收到重传数据后,发现 SN 依旧为 0。那么说明主机并没有成功收到上一此从机发送的响应包,因此继续重传上一次数据。
- 主机此时收到从机的响应包了,那么就更新 SN = 1 ,并且期望从机回复该数据包,因此 NESE = 1。
- 从机收到数据包后,更新 SN 和 NESN。
- 通过上面的例子,我们现在明白了,整个 BLE 的重传机制。那么我们再举几个例子加深理解。
- 假如,我设置了从机延迟,从机可以忽略主机的数据包,那么整个机制是怎么样的呢?
- 主机首先发送数据包给从机,从机进行忽略。此时主机继续重发,从机继续忽略。然后主机继续重发,一直重发到从机发送回包时才会开始发下一包其他数据,或者超过监管超时时间,发生断连。
- 上面这个需要注意一点,从机发送的回报,有可能是空包,也有可能是包含数据的数据包。如下图,主机发送 LL_VERSION_IND,从机回复的却是 LL_FEATURE_RSP。
core 5.3的 2861 页存在这样如下描述。因此,这种 LL 层 PDU 发生碰撞是允许的,整个数据包分析要结合整个数据交互流程才可知道。
Note: Because Link Layer PDUs are not required to be processed in real time, it is possible for the local Controller to have queued but not yet transmitted an LL_LENGTH_REQ PDU when it receives an LL_LENGTH_REQ PDU from the peer device. In this situation each device responds as normal; the resulting collision is harmless.
HOST 层
- 对于 HOST 层而言,数据包是必达的。因为 Control 层存在 CRC 和重传机制,因此 HOST 层数据只要传递给了 Control 层,只要没有断连,那么数据就一定会正确的传递到对端设备。
- 我们需要注意的一点是,不是 req 的命令,虽然协议栈底层确保了该命令必达对方,但应用层其实并不知道。而 req 命令会产生回调函数,这会应用层是知道的,从而实现特定的通讯逻辑。但是,这两种命令都会产生回包确保数据必达。
应用层
- 在 HOST 层,我们知道数据是必达的,那么应用层数据还有讲的必要吗?很显然,是有必要的。因为很多从事应用开发的人会经常说,数据丢包数据丢包。其实,这个并不是丢包,而是你的数据包正确没有完整安全地送达到协议栈射频 FIFO 。这才导致了所谓的丢包。
- 如果应用层没有及时的处理,资源不足(如内存不足),处理异常,短时间发送太多数据,导致对端设备接收端的缓冲区被填满,新的数据包被丢弃等行为将会导致数据不能成功的存储在射频 FIFO中,因此存在所谓的丢包问题。
总结
- 通过上面的分析,我们也将能够知道,为什么 BLE 设备厂商从来不宣传丢包率,而是宣传速率的问题了吧。
- 因为只要你程序写对了,数据完好无损的放入了射频FIFO中,数据就一定会到达对端设备。而空中的丢包,将会以速率的形式体现,因为你空中包丢包次数一多,那么数据就需要多次进行重传,那么最终拖慢传输速率。
参考
- 低功耗蓝牙ATT/GATT/Profile/Service/Characteristic规格解读
- 《低功耗蓝牙开发权威指南》7.8.4 确认