4、BLE广播包解析:广播信道与数据信道、广播PDU类型、广播数据格式
各位同学,欢迎来到第四章。前面我们聊了BLE协议栈的架构,也看了抓包工具怎么用。今天咱们来点真格的——直接拆解一个广播包。
你想想看,一个蓝牙设备从开机到被手机发现,中间发生了什么?说白了,就是它在不停地“喊话”。这个喊话的过程,就是广播。我当年刚接触BLE时,觉得广播嘛,不就是发几个字节吗?结果一抓包,发现里面门道还挺多。今天我就把这几年的经验掰开揉碎讲给你听。
4.1 广播信道与数据信道
BLE在2.4GHz频段里干活,一共划了40个信道,编号0到39。但这40个信道不是平起平坐的,它们分成了两拨:广播信道和数据信道。
| 信道类型 | 信道编号 | 中心频率 | 用途 |
|---|---|---|---|
| 广播信道 | 37、38、39 | 2402 MHz、2426 MHz、2480 MHz | 设备发现、广播、连接建立 |
| 数据信道 | 0~36(共37个) | 2404~2478 MHz(间隔2 MHz) | 连接后的数据收发 |
为什么广播信道只有3个?我刚开始也觉得奇怪,37个数据信道,才3个广播信道,够用吗?
其实这是故意的。BLE设计者希望广播设备能快速被找到,所以选了3个在频段上分布比较开的信道——37在最低端,38在中间,39在最高端。这样不管环境怎么干扰,总有一个信道能通。我在项目中遇到过,有些厂房里2.4GHz Wi-Fi特别多,信道38经常被挤爆,但37和39还能正常工作。这就是3个信道的妙处。
数据信道就简单了,连接建立之后,主设备和从设备在这37个信道上跳来跳去地通信,这叫跳频。跳频的好处是抗干扰,这个我们后面讲连接事件时再细说。
核心要点:广播只在37/38/39三个信道上进行。抓广播包时,你只需要监听这三个信道就够了。数据信道有37个,但那是连接之后的事。
4.2 广播PDU类型
广播包不是随便发的,它有一套严格的格式。我们先看广播信道PDU的类型。嗯,这里要注意,PDU就是Protocol Data Unit,协议数据单元,说白了就是“这一帧里到底装了什么消息”。
广播PDU主要分这么几类:
- ADV_IND:可连接的非定向广播。最常用,手机扫描时看到的设备基本都是这种。
- ADV_DIRECT_IND:可连接的定向广播。指定了目标设备地址,别人收到也不处理。
- ADV_NONCONN_IND:不可连接的非定向广播。只发不收,适合广播者不想被连接的情况。
- ADV_SCAN_IND:可扫描的非定向广播。允许别人发扫描请求来获取更多数据。
- SCAN_REQ / SCAN_RSP:扫描请求和扫描响应。这是扫描者和广播者之间的“握手”。
- CONNECT_REQ:连接请求。扫描者想跟广播者建立连接时发的。
我列个表,方便你对比记忆:
| PDU类型 | 可连接 | 可扫描 | 定向 | 典型场景 |
|---|---|---|---|---|
| ADV_IND | 是 | 是 | 否 | 手机、手环、耳机广播 |
| ADV_DIRECT_IND | 是 | 否 | 是 | 快速重连 |
| ADV_NONCONN_IND | 否 | 否 | 否 | 信标(Beacon) |
| ADV_SCAN_IND | 否 | 是 | 否 | 需要被动扫描获取额外数据 |
你可能会问:ADV_DIRECT_IND为什么不可扫描?因为定向广播的目标很明确,不需要别人来扫描。我曾经调试过一个手环快速重连的问题,设备发ADV_DIRECT_IND,手机就是收不到。后来发现是白名单没配对,地址对不上。这种坑,踩过一次就记住了。
实战技巧:抓包时,如果你看到大量ADV_DIRECT_IND包,说明设备在尝试快速重连。如果一直连不上,先检查目标地址对不对。
4.3 广播数据格式(AD Structure)
好了,现在我们知道广播包有哪些类型了。但广播包里到底装了啥?这就得看AD Structure了。
AD的全称是Advertising Data,广播数据。它的结构很简单,就是一个接一个的“数据块”,每个块叫一个AD Structure。格式如下:
+--------+--------+--------+--------+--------+
| Length | AD Type | AD Data ...
| (1字节) | (1字节) | (Length-1字节)
+--------+--------+--------+--------+--------+
每个AD Structure由三部分组成:
- Length:1字节,表示后面AD Type + AD Data的总长度。
- AD Type:1字节,表示数据类型。比如0x01表示Flags,0x09表示Complete Local Name。
- AD Data:Length-1字节,具体的数据内容。
举个例子,你抓到一个广播包,里面有一段数据:02 01 06 09 09 42 4C 45 5F 44 65 76 69 63 65。怎么解析?
我来手把手拆一遍:
- 第一个字节
02:Length=2,说明这个AD Structure总长2字节。 - 第二个字节
01:AD Type=0x01,这是Flags。 - 第三个字节
06:AD Data,Flags的值是0x06,表示LE General Discoverable Mode + BR/EDR Not Supported。 - 第四个字节
09:下一个AD Structure的Length=9。 - 第五个字节
09:AD Type=0x09,Complete Local Name。 - 后面8个字节
42 4C 45 5F 44 65 76 69 63 65:ASCII码,对应字符串"BLE_Device"。
你看,就这么简单。我刚开始手动解析时,经常数错字节。后来养成了一个习惯:先在纸上画格子,一格一个字节,标上Length、Type、Data,再对照着看。这个方法虽然土,但不容易出错。
注意:广播包的总长度不能超过31字节(PDU里最多31字节的有效载荷)。所以AD Structure不能太多,要精打细算。我曾经见过一个产品,把设备名称、服务UUID、厂商自定义数据全塞进去,结果超了,最后只能砍掉厂商数据。设计广播包时,一定要先算好预算。
4.4 常见AD Type一览
AD Type有很多种,但常用的就那几个。我列个表,你抓包时对照着看:
| AD Type值 | 名称 | 说明 |
|---|---|---|
| 0x01 | Flags | 广播模式、BR/EDR支持等标志位 |
| 0x02 | Incomplete List of 16-bit Service UUIDs | 不完整的16位服务UUID列表 |
| 0x03 | Complete List of 16-bit Service UUIDs | 完整的16位服务UUID列表 |
| 0x08 | Shortened Local Name | 缩短的设备名称 |
| 0x09 | Complete Local Name | 完整的设备名称 |
| 0xFF | Manufacturer Specific Data | 厂商自定义数据 |
Flags这个字段特别重要。它的每一位都有含义:
- Bit 0:LE Limited Discoverable Mode
- Bit 1:LE General Discoverable Mode
- Bit 2:BR/EDR Not Supported
- Bit 3:Simultaneous LE and BR/EDR to Same Device Capable (Controller)
- Bit 4:Simultaneous LE and BR/EDR to Same Device Capable (Host)
最常见的Flags值是0x06,表示“LE通用可发现模式 + 不支持BR/EDR”。你抓到的绝大多数BLE设备,Flags都是这个值。
4.5 广播包整体结构图
说了这么多,咱们用一张图把广播包的完整结构串起来。下面这张SVG图,是我自己画的,把广播信道PDU、MAC地址、AD Structure都标清楚了。
这张图把广播包的层次关系画得很清楚。从上到下依次是:PDU层 → 广播数据层 → 具体的AD Structure。每个AD Structure都是独立的,你可以根据需要组合。
4.6 实战:抓包分析一个真实的广播包
光说不练假把式。咱们拿一个真实的抓包数据来练练手。
假设你用Wireshark抓到了一个广播包,原始数据是这样的(十六进制):
04 3E 2B 02 01 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00