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请求在连接后只会发一次。
4. MTU响应
当服务端接收到MTU请求后,需要回应给客户端MTU应答。应答的MTU代表服务端本地能够接收最大的数据长度,该值同样需要大于或等于ATT_MTU。
5. MTU交换流程
MTU交换的本质不是在协商,而是在MTU请求或响应的时候告诉对方自己能够接收的最大数据长度是多少。在MTU应答后,两者的数据交互就使用两者能接收的MTU最小值了。
6. 既是客户端又是服务端的MTU情况
如果一个设备既是客户端又是服务端,那么有一下几点需要注意:
- 该设备的MTU请求和MTU应答的大小需要一致。
- 如果在一个方向交换了,相当于两个方向都有效。相当于只需要交换一次。
- 如果MTU请求之后,但没有接收到应答之前,不可以向对端设备发送通知或指示。
- 如果一个ATT PDU发生在MTU请求后但是在MTU响应之前,这个ATT PDU的应答还是使用默认MTU。如下图:
7. 通过空中包来看看MTU交换
该例子是服务端发起MTU请求,客户端回复MTU响应。
服务端MTU请求:
客户端MTU响应:
8. 总结
在低功耗蓝牙连接中,ATT协议默认的MTU长度为23字节。按照一个字节的类型操作码(请求、响应、命令、指示、确认、通知)以及最少2个字节的操作句柄来算,数据传输字节最多不超过20个字节。在两个设备连接初期,谁也不知道对方能够支持的MTU是多少,因此数据交换按照默认的MTU来,即23个字节。
如果设备想要发送比默认MTU大的数据包,那么它就要协商一个更大的MTU。客户端的请求包含客户端接收的MTU长度;服务器响应则包含服务器接受的MTU长度。对于同时是是客户端服务器的设备而言,二者提供的接收MTU长度中较小的那个即是连接将会使用的MTU长度(一般两者会相等)。
低功耗蓝牙在功耗方面确实是想尽了心思,MTU越大功耗越大,最大传输速率越大,反之相反。
蓝牙协议文档里面提到只有客户端可以发起MTU请求。但是本人实践是服务端发起请求也是行,只要客户端收到请求后回应MTU响应就可以。