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。怎么解析?

我来手把手拆一遍:

  1. 第一个字节02:Length=2,说明这个AD Structure总长2字节。
  2. 第二个字节01:AD Type=0x01,这是Flags。
  3. 第三个字节06:AD Data,Flags的值是0x06,表示LE General Discoverable Mode + BR/EDR Not Supported。
  4. 第四个字节09:下一个AD Structure的Length=9。
  5. 第五个字节09:AD Type=0x09,Complete Local Name。
  6. 后面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都标清楚了。

BLE广播包结构图 BLE广播包(ADV_IND)完整结构 广播信道PDU(Protocol Data Unit) PDU类型(4bit) | 保留(2bit) | 信道选择(2bit) | 发送地址 | 接收地址 | 广播数据 广播数据(Advertising Data) 最大31字节,由多个AD Structure组成 AD Structure 1 Length: 0x02 Type: 0x01 (Flags) Data: 0x06 AD Structure 2 Length: 0x09 Type: 0x09 (Name) Data: "BLE_Device" AD Structure 3 Length: 0x05 Type: 0xFF (厂商) Data: 厂商自定义 注意:所有AD Structure的Length之和 + 每个Structure的1字节Type + 1字节Length ≤ 31字节 超出部分会被接收端丢弃,所以设计广播包时要精打细算

这张图把广播包的层次关系画得很清楚。从上到下依次是: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