【基本解决】蓝牙数据传输数据单次超过990字节时被截断分段多次传输

【背景】

Android中,用蓝牙发送数据,结果出现,超过990的字节的大批量的数据,就会被截断。

【解决过程】

1.google去搜:

Bluetooth 990 bytes

找到:

有人遇到,但是无解:

streaming – What is the Maximum packat size to send data over bluetooth in Android? – Stack Overflow

2.android – RFCOMM receiving data with 1 L2CAP packet missing – Stack Overflow

提到了“My android mobile bluetooth supporting maximum RFCOMM payload is 990 bytes”

不过好像其遇到的问题不一样:

发送了1K=2014=990+34,结果990丢失了,而不是截断的事情了。

3.Bluetooth data being split on Android device – Stack Overflow

说是:

RFCOMM中,就像串口,是没有Package包的概念的,只有字节流;

然后有时候多个小的数据包,又会被放在一起传输->一次性接收到的,是多个小的数据包。

而分段的大小,即一次性最大传输多少个,此处的990,是取决于每个蓝牙芯片内部的参数设置的。

->感觉说的也不一定对。。。

4.java – Android – Pass object via bluetooth – Stack Overflow

也有人遇到类似问题。

5.看到:

Setting up Bluetooth — Clay and Galileo

Intel® Galileo Boards and Kits — Bluetooth Setup

中关于蓝牙配置时,有个:

# hciconfig
hci0: Type: BR/EDRBus: USB
BD Address: B4:B6:76:8D:AB:07ACL MTU: 310:10SCO MTU: 64:8
UP RUNNING
RX bytes:990 acl:0 sco:0 events:44 errors:0
TX bytes:738 acl:0 sco:0 commands:44 errors:0

其中的

RX bytes:990

感觉像是说:

一次性最多接受990个字节

如果是的话,那么:

TX bytes:738

或许就意味着:

一次性最多发送738个字节

6.再去搜:

Bluetooth RFCOMM max payload

找到:

List of Bluetooth protocols – Wikipedia, the free encyclopedia

都提到了:

L2CAP’s functions include:

  • Multiplexing data between different higher layer protocols.
  • Segmentation and reassembly of packets.
  • Providing one-way transmission management of multicast data to a group of other Bluetooth devices.
  • Quality of service (QoS) management for higher layer protocols.

L2CAP is used to communicate over the host ACL link. Its connection is established after the ACL link has been set up.

In basic mode, L2CAP provides packets with a payload configurable up to 64 kB, with 672 bytes as the default MTU, and 48 bytes as the minimum mandatory supported MTU.

根据:

Segmentation and reassembly of packets

感觉应该是L2CAP层负责数据包的,分段,拆分,和合并的。

7.根据:

http://authors.phptr.com/bluetooth/bray/pdf/cr_ch10.pdf

structure of an RFCOMM frame

“10.5.4 Data

The data field is only present in UIH frames. There must be an integral number of bytes in the data up to 32767. The size limit is set by the Maximum Transmission Unit (MTU) on

L2CAP packets, so if a system has a smaller L2CAP MTU, the size of RFCOMM data will also be restricted.”

好像是:

RFCOMM中最大的payload是32767字节(而不是上面说的64KB=65536)

另外也在:

SPP Maximum Payload – Bluetooth® CC256x Forum – Wireless Connectivity – TI E2E Community

中看到RFCOMM协议的细节构成:

+----------+----------+--------------------+----------+--------------------+---------+
| Address  | Control  | Length Indicator  | Credits   | Data/Information   |   FCS   |
+----------+----------+--------------------+----------+--------------------+---------+
  1 Octet     1 Octet     1 or 2 Octets       1 Octet                        1 Octet

8.31.5. Bluetooth

%l2control -a 00:02:72:00:d4:1a read_channel_list
L2CAP channels:
Remote BD_ADDR     SCID/ DCID   PSM  IMTU/ OMTU State
00:07:e0:00:0b:ca    66/   64     3   132/  672 OPEN

好像是:

IMTU==Input MTU 是132字节?

OMTU==Output MTU 是672字节?

9.根据:

Higher Layer Losses | How Fast is Bluetooth? | InformIT

“For example, if we assume that a regular stream of 20-byte packets is sent via RFCOMM, L2CAP, and HCI, this is what will happen:

RFCOMM adds a byte of address information, a byte of control information, a byte of length indicator information, and a byte of Frame Check Sequence (FCS) information. With these extra 4 bytes, L2CAP receives a 24-byte packet. RFCOMM escapes some characters, so the data rate could be even worse, depending on the data patterns sent.

L2CAP adds 2 bytes of length information and 2 bytes of channel ID onto the packet. So, having received 24 bytes from RFCOMM, L2CAP passes 28 bytes on to HCI.”

应该是:

HCI

== 4字节(2字节长度+2字节channel ID) + L2CAP

== 4字节(2字节长度+2字节channel ID) +(4字节(1字节地址信息+1字节控制信息+1字节长度指示信息+1字节FCS) + RFCOMM)

简单说就是:

HCI

= L2CAP                       + 4字节

=(RCFOMM+4字节)+ 4字节

 

10.

参考:

RFCOMM

type 1 and type 2 RCFOMM devices

先明白蓝牙协议的层次关系:

RFCOMM

L2CAP

HCI

 

11.SPP Maximum Payload – Bluetooth® CC256x Forum – Wireless Connectivity – TI E2E Community

说是:

L2CAP的MTU最大是128字节

当配置L2CAP通道的时候,就会通知双方的MTU是多少。

 

MTU表示的含义是,可以通过L2CAP通道去接收的最大的SDU(Service Data Unit)的字节数是多少

BlueMSP430 EtherMind SPP SDK用的RFCOMM的MTU是128字节

意味着:

针对此RFCOMM协议,其底层的L2CAP中Payload是128字节

换句话说:

此处的128不包含L2CAP的头信息

->L2CAP

==payload+header/tail

=128+4

 

而用到了RFCOMM的协议(比如SPP),其中最大的数据包packet长度,是由

在建立RFCOMM连接的参数协商Parameter Negotiation阶段

去确定的帧大小Frame Size决定的。

 

L2CAP MTU的值是不对称的:

两个方向可以是不一样的:发送和接收的MTU可以不一样

而帧大小是统一的

当计算帧大小时,两个方向,发送和接收,的L2CAP MTU的最小值则要考虑进去

 

比如:

BlueMSP430 SPP SDK 连接到PC(比如默认用的是微软的蓝牙协议栈)

往往MTU都是大于128字节的->因为PC端有足够的资源和内存,可以处理更大批量的数据包

所以此时BlueMSP430 SPP的最小MTU是128字节

 

去掉6字节的头尾,还剩128-6=122字节

 

12.后来去折腾,寻找其他hciconfig的用法时,也看到其他地方的hciconfig输出中RX的值是其他的值,比如:

Android blueZ HCI(一):hciconfig实现及常用方法 – CLK – 博客频道 – CSDN.NET

(1)

hciconfig all output example

 

RX是3944

TX是2311

(2)

hcifonfig para a show all info

root@android:/ # hciconfig -a  
hciconfig -a  
hci0:   Type: BR/EDR  Bus: UART//蓝牙的接口类型,这个是UART的,还有USB、PCI…………  
        BD Address: 00:16:53:96:22:53  ACL MTU: 1021:8  SCO MTU: 120:10//蓝牙地址  
        UP RUNNING PSCAN//命令状态  
        RX bytes:2846 acl:0 sco:0 events:67 errors:0  
        TX bytes:2034 acl:0 sco:0 commands:80 errors:0  
        Features: 0xff 0xff 0x8d 0xfe 0x9b 0xbf 0x79 0x83  
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3//支持数据包  
        Link policy: RSWITCH HOLD SNIFF PARK  
        Link mode: SLAVE ACCEPT//连接的类型,是主设备、从设备  
        Name: 'sp8825c1'//蓝牙名称  
        Class: 0x5a020c//蓝牙的类型  
        Service Classes: Networking, Capturing, Object Transfer, Telephony//支持的类型  
        Device Class: Phone, Smart phone  
        HCI Version: 2.1 (0x4)  Revision: 0x1250//HCI版本  
        LMP Version: 2.1 (0x4)  Subversion: 0x1250//LMP版本  
        Manufacturer: Ericsson Technology Licensing (0)//作者 

RX是2846

TX是2034

(3)

linux下使用蓝牙设备 bluetooth hciconfig hcitool

hciconfig hci0 type usb

RX是1459

TX是764

(4)

Anonymize Bluetooth Devices On Linux Using hciconfig Utility ~ Linux | Android | Windows Tricks, Hacks and Exploits

hci0:    Type: BR/EDR  Bus: USB
    BD Address: E4:D5:3D:F2:7B:66  ACL MTU: 1021:8  SCO MTU: 64:1
    UP RUNNING PSCAN 
    RX bytes:1105 acl:0 sco:0 events:38 errors:0
    TX bytes:2088 acl:0 sco:0 commands:38 errors:0

RX是1105

TX是2088

(5)

Resources/HowTo/SamsungBTInOrigen – Linaro Wiki

root@linaro-alip:~# hciconfig -a
hci0:   Type: BR/EDR  Bus: UART
        BD Address: A0:0B:BA:FF:FF:FF  ACL MTU: 310:10  SCO MTU: 64:8
        UP RUNNING PSCAN
        RX bytes:1306 acl:0 sco:0 events:31 errors:0
        TX bytes:1118 acl:0 sco:0 commands:30 errors:0
        Features: 0xff 0xff 0x8f 0xfe 0x9b 0xff 0x59 0x87
        Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
        Link policy: RSWITCH HOLD SNIFF PARK
        Link mode: SLAVE ACCEPT
        Name: 'linaro-alip-0'
        Class: 0x4a0100
        Service Classes: Networking, Capturing, Telephony
        Device Class: Computer, Uncategorized
        HCI Version: 3.0 (0x5)  Revision: 0x1aa1
        LMP Version: 3.0 (0x5)  Subversion: 0x1aa1
        Manufacturer: Cambridge Silicon Radio (10)

RX是1306

TX是1118

 

13.然后问题转化为:

关于Android端的(和PC端,后期再说)蓝牙的MTU值,或者说payload值的,具体是多少

去google搜:

android bluetooth MTU

参考:

Bluetooth MTU – stevenliyong 的专栏 – 博客频道 – CSDN.NET

应该说是:

Android端,蓝牙的MTU的值,一般来说,默认估计也是672之类的值

而PC端,MTU值一般很大(因为内存足够用)比如Ubuntu,常见的是990

而MTU的值的大小,影响了实际的蓝牙传输速度,MTU越高,速度越快,但是同时对于内存占用相对越多些。

 

比如那人的例子:

PC端:

开发板(等价于Android手机)端:

    MTU==672->20KB(1MB/50s)

    MTU==60000->蓝牙速度:75KB(1MB/13s)

注:

手机端的蓝牙的L2CAP底层的内存占用就高了些(具体多少,暂未知)。

 

14.不过另外这里:

external-bluetooth-bluedroid/gatt_api.h at master · tieto/external-bluetooth-bluedroid · GitHub

关于bluedroid中的GATT,也有个MTU

/* MAX GATT MTU size
*/
#ifndef GATT_MAX_MTU_SIZE
    #define GATT_MAX_MTU_SIZE     517
#endif

15.这里:

bluetooth lowenergy – Android BLE MTU size, has anyone sniffed it? – Stack Overflow

提到了:

client和server可以通过:

Exchange MTU Request and Response PDUs

去改变默认的MTU值,然后之后的通讯就以两者最小的MTU为基准,进行通信。

 

【总结】

首先,从蓝牙的协议关系来说是:

HCI=L2CAP+4字节=RFCOMM+4字节+4字节=RFCOMM+8字节

简写为:

HCI=L2CAP+4=RFCOMM+8

 

 

而我们常用的协议本身内部传输的有效数据叫做payload,好像有的地方也叫MTU(Maximum Transmission Unit),然后有的地方也被叫做frame帧:

不过,一般来说,其关系是:

MTU=Frame=Header/Tail + Payload

 

如图:

协议

Payload或MTU范围

Payload或MTU默认值

RFCOMM

0-32KB

默认为672字节

其他的比如接收RX990/发送TX738

L2CAP

0-64KB

 

HCI

 

310/10

 

不过其实还是没有研究的透彻,有空再说。



发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量