目录:

  • 1. 写在前面
  • 2. MTU
  • 3. MTU请求
  • 4. MTU响应
  • 5. MTU交换流程
  • 6. 既是客户端又是服务端的MTU情况
  • 7. 通过空中包来看看MTU交换
  • 8. 总结


1. 写在前面

本文由蓝牙核心文档Core_5.2 Vol_3 Part_A 5.1 与 Core_5.2 Vol_3 Part_F 3.4.2展开。

2. MTU

全名:MAXIMUM TRANSMISSION UNIT;中译为:最大传输单元,意思是数据传输的时候一次最大可以传输的字节数。MTU在请求或应答的时候占用2个字节,在ACL-U逻辑链路上的最小值是48,在LE-U逻辑链路上的最小值是23。在MTU协商中,请求的MTU值不能小于该链路的最小值,如果小于最小值的话可能被对端设备拒绝甚至断开连接。
MTU交换发生在ATT协议层。

3. MTU请求

请求是从客户端发送给服务端通知自己的最大接收长度,然后请求服务端回应本地的最大接收长度。客户端接收MTU需要大于或等于ATT_MTU大小。一般MTU请求在连接后只会发一次。

android 设置蓝牙mtu未生效 安卓蓝牙mtu_服务端

4. MTU响应

当服务端接收到MTU请求后,需要回应给客户端MTU应答。应答的MTU代表服务端本地能够接收最大的数据长度,该值同样需要大于或等于ATT_MTU。

android 设置蓝牙mtu未生效 安卓蓝牙mtu_android 设置蓝牙mtu未生效_02

5. MTU交换流程

MTU交换的本质不是在协商,而是在MTU请求或响应的时候告诉对方自己能够接收的最大数据长度是多少。在MTU应答后,两者的数据交互就使用两者能接收的MTU最小值了。

6. 既是客户端又是服务端的MTU情况

如果一个设备既是客户端又是服务端,那么有一下几点需要注意:

  • 该设备的MTU请求和MTU应答的大小需要一致。
  • 如果在一个方向交换了,相当于两个方向都有效。相当于只需要交换一次。
  • 如果MTU请求之后,但没有接收到应答之前,不可以向对端设备发送通知或指示。
  • 如果一个ATT PDU发生在MTU请求后但是在MTU响应之前,这个ATT PDU的应答还是使用默认MTU。如下图:

7. 通过空中包来看看MTU交换

该例子是服务端发起MTU请求,客户端回复MTU响应。

android 设置蓝牙mtu未生效 安卓蓝牙mtu_iot_03


服务端MTU请求:

android 设置蓝牙mtu未生效 安卓蓝牙mtu_android 设置蓝牙mtu未生效_04


客户端MTU响应:

android 设置蓝牙mtu未生效 安卓蓝牙mtu_客户端_05

8. 总结

在低功耗蓝牙连接中,ATT协议默认的MTU长度为23字节。按照一个字节的类型操作码(请求、响应、命令、指示、确认、通知)以及最少2个字节的操作句柄来算,数据传输字节最多不超过20个字节。在两个设备连接初期,谁也不知道对方能够支持的MTU是多少,因此数据交换按照默认的MTU来,即23个字节。
如果设备想要发送比默认MTU大的数据包,那么它就要协商一个更大的MTU。客户端的请求包含客户端接收的MTU长度;服务器响应则包含服务器接受的MTU长度。对于同时是是客户端服务器的设备而言,二者提供的接收MTU长度中较小的那个即是连接将会使用的MTU长度(一般两者会相等)。
低功耗蓝牙在功耗方面确实是想尽了心思,MTU越大功耗越大,最大传输速率越大,反之相反。
蓝牙协议文档里面提到只有客户端可以发起MTU请求。但是本人实践是服务端发起请求也是行,只要客户端收到请求后回应MTU响应就可以。