今天发现 Android 手机微信小程序中收到的 BLE 蓝牙数据包出现了粘包的情况。
确认校验失败的数据包实际长度
校验失败的数据包:
- ab0002a20800a8ba ab0002a21a02b8ba ab0002a2
- ab00022638100cba ab000628380bb80b b80bb8a5
- ab000212380820ba ab00021338052cba ab000214
长度均为 20 个字节(MTU 的默认大小,也是最小值); 02 包对应的长度为 8 个字节。
单个包,以 ab 开始,ba 结束。可以看到明显的两个/甚至三个包的粘包现象。
校验成功的
- ab000423380c1c0b5450ba
- ab00040b382710d8f028ba
长度为 11 个字节
猜测,当一个包的长度小于 10 字节时,会尝试向后面拼包。(实际不是这样,应该是高频引起的)
被截断之后,后续数据并没有补发。
根本原因:指令收发过快会有蓝牙粘包问题
猜测是安卓系统在蓝牙接收数据的处理上有时间的设置。如果硬件发送给设备端的速度太快。前一个包可能会和后一个包粘连。
例如接收 A,B,C。过快时会受到 A+B 前半段, B 后半段加 C 两个包。时序上没有错误。但包之间会粘连。包的数量也会变化。
常用的解决方案:
- 限制 BLE 蓝牙设备的发送频率。
- 每个包固定大小为 20 字节,这样不会粘包
- 自定义协议上设置一个结束位,用于分割
- 先接收数据包,缓存,并拼接,然后集中处理
粘包的英文
packet fragmentation
微信小程序获取 MTU 值
https://developers.weixin.qq.com/miniprogram/dev/api/device/bluetooth-ble/wx.getBLEMTU.html
- 小程序中 MTU 为 ATT_MTU,包含 Op-Code 和 Attribute Handle 的长度,实际可以传输的数据长度为 ATT_MTU - 3。例如 23, 实际数据长度为 20.
- iOS 系统中 MTU 为固定值;安卓系统中,MTU 会在系统协商成功之后发生改变,建议使用 wx.onBLEMTUChange 监听。
参考
- http://events.jianshu.io/p/46daabc7787d
微信关注我哦 👍
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式