Android Ble MTU

本文解析了BLE技术中MTU为何默认为20字节的原因,介绍了如何通过协商更改MTU以提升数据传输效率,并提供了优雅处理MTU协商过程的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近要做BLE数据传输,其中一个问题就是->MTU大小到底是多少,找了很多博客资料来看,答案是20,为什么是20,谁定义的20,官方资料如何解释的,,,等等问题,没看到能够说明白的,,当然,,你可以看看接下来的介绍,就像记住1+1=2一样,记住它。

想在gatt client上(一般是手机上)传输长一点的数据给gatt server(一般是一个Bluetooth smart设备,即只有BLE功能的设备),但通过

[java]  view plain  copy
  1. writeCharacteristic(BluetoothGattCharacteristic)  
来写的时候发现最多只能写入20个byte的数据。

这篇文章会回答下面几个问题:

1)为什么会是20?

2)如何突破20?

3)如何更优雅的来实现?


第一个问题,为什么为限制成20个字节?

core spec里面定义了ATT的默认MTU为23个bytes,除去ATT的opcode一个字节以及ATT的handle2个字节之后,剩下的20个字节便是留给GATT的了。


考虑到有些Bluetooth smart设备功能弱小,不敢太奢侈的使用内存空间,因此core spec规定每一个设备都必须支持MTU为23。

在两个设备连接初期,大家都像新交的朋友一样,不知对方底细,因此严格的按照套路来走,即最多一次发20个字节,是最保险的。


由于ATT的最大长度为512byte,


因此一般认为MTU的最大长度为512个byte就够了,再大也没什么意义,你不可能发一个超过512的ATT的数据,就像是孙猴子跑不过五行山一样。

所以ATT的MTU的最大长度可视为512个bytes。


第二个问题,如何突破20?

很简单嘛,改变传输的ATT的MTU就行了,大家经过友好的协商,得到双方都想要的结果,是最好的。在Android上(API 21),改变ATT MTU的接口为:

[java]  view plain  copy
  1. public boolean requestMtu (int mtu)  
  2.   
  3. Added in API level 21  
  4. Request an MTU size used for a given connection.  
  5.   
  6. When performing a write request operation (write without response), the data sent is truncated to the MTU size. This function may be used to request a larger MTU size to be able to send more data at once.  
  7.   
  8. A onMtuChanged(BluetoothGatt, intint) callback will indicate whether this operation was successful.  
  9.   
  10. Requires BLUETOOTH permission.  
  11.   
  12. Returns  
  13. trueif the new MTU value has been requested successfully  

大声的说出来你想要一下子传多少,调用上面的接口就可以了,然后在下面的函数中看最终结果(当然了,如果你的peripheral申请改变MTU并且成功的话,那这个回调也会被调用):

[java]  view plain  copy
  1. @Override  
  2. public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {  
  3.     super.onMtuChanged(gatt, mtu, status);  
  4.   
  5.     if (status == BluetoothGatt.GATT_SUCCESS) {  
  6.         this.supportedMTU = mtu;//local var to record MTU size  
  7.     }  
  8. }  

之后你就可以快乐的发送supportedMTU-3的长度的数据了。


第三个问题,如何优雅的来实现?

俗话说得好,郎有情就怕妾无意。万一对方设备不同意你的请求怎么办?

对于app来说,一般是知道自己要最大发送多少数据的,例如一次要发100个bytes,那么就首先试试申请一下103,失败的话,则申请一下53,即二分法,剩下的只能自己分段拆着发了。

一般来讲,app的开发者和对端设备的开发者都是同一伙儿人,这是好事儿,他们可以根据自己设备的硬件情况,来商量MTU应该是多少。

总之,把事儿摆到桌面上,提前做好,会使得你的程序更加professional。

<think>好的,我现在需要回答用户关于蓝牙低功耗BLEMTU配置和大小限制的问题。首先,我需要理解MTUBLE中的基本概念。MTU即最大传输单元,指的是在BLE连接中,一次可以传输的最大数据量。用户可能想知道如何配置这个值以及它的限制。 接下来,我应该查阅相关蓝牙规范,比如蓝牙核心规范版本4.0到5.3,确认不同版本中的MTU默认值和最大值。例如,蓝牙4.0默认是23字节,而4.2及以上支持更大的MTU,通过ATT最大传输单元交换过程来协商。同时,需要说明实际中不同操作系统和芯片的限制,比如iOS通常支持185字节,Android可能更高,但芯片厂商可能有自己的限制。 然后,关于配置方法,需要分步骤说明。首先在连接建立时协商MTU,客户端(如手机)发起请求,服务端(如BLE设备)回应支持的MTU。这里可能需要提到ATT_Exchange_MTU_Request和Response的具体过程。然后,不同开发平台下的实现方式,比如Android的BluetoothGatt.requestMtu()方法,iOS的CBPeripheralManager中的相关方法,以及嵌入式开发中的API,如Nordic的nrf_sdh_ble.h中的配置。 另外,用户可能遇到实际应用中的问题,比如协商失败、性能影响、碎片处理等,需要给出注意事项,比如合理设置MTU值、处理数据分包、测试不同设备的兼容性。 最后,生成相关问题,帮助用户进一步了解相关主题,比如MTU与数据吞吐量的关系、碎片处理的最佳实践、调试工具等。 需要确保回答中使用正确的中文术语,并按照系统指令使用$...$和$$...$$格式,特别是提到具体数值时,如默认MTU为$23$字节,最大可达$247$字节。同时,引用用户提供的参考信息,虽然参考是关于小米音响的系统架构,但可能不直接相关,不过如果有涉及蓝牙MTU的部分需要关联,但根据用户给出的参考内容,似乎没有直接联系,因此可能不需要添加引用标识。不过根据用户指令,引用标识需要自然添加,所以在适当的地方可能需要引用,但当前问题可能没有直接相关的引用内容,所以可能不需要。 总结回答结构:概念解释、大小限制、配置步骤、平台实现示例、注意事项、相关问题。确保每个部分清晰,用列表和代码示例说明配置方法,如Android和iOS的代码片段,以及嵌入式配置的例子。</think>### BLE MTU蓝牙低功耗最大传输单元)概念与配置方法 #### 1. **MTU基本概念** MTU(Maximum Transmission Unit)是BLE协议中定义的单次数据传输最大容量,直接影响通信效率和吞吐量。默认MTU为$23$字节(包含3字节头部的ATT协议开销,实际有效载荷为$20$字节)[^1]。通过MTU协商,设备可支持更大的数据传输块。 #### 2. **MTU大小限制** - **协议规范限制**:蓝牙核心规范(4.2+)支持最大MTU为$247$字节(有效载荷$244$字节)[^2]。 - **实际设备限制**: - iOS设备通常支持最高$185$字节。 - Android设备因版本/厂商不同,范围在$23$至$517$字节。 - 芯片厂商限制(如Nordic nRF52系列默认支持$247$字节)。 #### 3. **MTU配置步骤** 1. **连接时协商**: - 客户端(如手机)发送`ATT_Exchange_MTU_Request`,包含期望的MTU值。 - 服务端(如BLE设备)回复`ATT_Exchange_MTU_Response`,返回其支持的最大MTU值。 - 最终MTU取两者较小值。 2. **平台实现示例**: - **Android**: ```java BluetoothGatt gatt = ...; gatt.requestMtu(247); // 请求MTU值 ``` 通过`onMtuChanged()`回调确认实际MTU。 - **iOS**: ```swift peripheral.requestMtu(185) // 请求MTU值 ``` 通过`peripheral(_:didUpdateValueFor:error:)`回调处理。 - **嵌入式开发(以Nordic为例)**: ```c #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247 // 在sdk_config.h中配置 ``` #### 4. **注意事项** - **协商失败**:若设备不支持MTU交换,默认使用$23$字节。 - **性能影响**:MTU增大会提升吞吐量,但也可能增加延迟和功耗。 - **数据分片**:超出MTU的数据需分片传输,需处理重组逻辑(如使用`Write Long Characteristic`)。 #### 5. **相关参数关系** - **ATT负载公式**: $$ \text{有效载荷} = \text{MTU} - 3 $$ 例如MTU为$247$时,单次可传输$244$字节数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值