我编写了一个应用程序,它在Linux上以非阻塞模式使用蓝牙LE L2CAP连接来读取/写入ATT数据包(使用socket(PF_BLUETOOTH, SOCK_SEQPACKET|SOCK_CLOEXEC, BTPROTO_L2CAP))。通常,当设备关闭或超出范围时,read()会给出errno=ETIMEDOUT。
然而,当蓝牙LE设备似乎还在工作的时候,read()给errno=ETIMEDOUT的频率比它应该的要高。超时的原因是什么?超时可配置吗?
我的Linux配置是3.13.0-24通用的;蓝牙核心服务器2.17。
发布于 2015-02-07 22:56:30
在建立的LE L2CAP套接字上的ETIMEDOUT错误实际上来自蓝牙适配器,在连续丢失了几个数据包之后。有多少取决于连接参数。一旦主服务器启动了与从节点的连接,主节点就会按每一个连接间隔(7.5ms-4s),并且当它听到ping消息时,该从节点将响应。如果任何一个设备在监视超时(100 If 32 S)后未能从另一个设备收到回音,它将关闭连接。第三个参数,从节点延迟 (0-499),允许从机通过不响应某些ping来节省电池电源。另见什么是连接参数?
操作系统在启动连接时设置默认连接参数。从服务器可能会推荐一组更合适的连接参数,以平衡电池续航时间、延迟和抵御障碍/干扰的能力,而操作系统也有机会批准这些参数(苹果操作系统将接受的连接参数范围见苹果蓝牙设计指南 )。但是如果从服务器没有建议一组新的参数,那么它就任由操作系统的默认设置决定了,操作系统的默认设置因操作系统而异。
在查看Wireshark中的hcidump btsnoop文件时,我的特定设备(蓝牙笔)似乎从未提出过不同的间隔和超时。因此,它的可靠性将取决于操作系统的默认值。
下面是实验确定的默认间隔和超时。
Linux3.13内置蓝牙适配器(core.c):
操作系统允许的间隔:50-70ms
蓝牙适配器选择的连接间隔: 67.5ms
监视超时:420 missing (断开连接前6丢失数据包)
iPhone 4S与iOS 7:
操作系统允许的间隔:未知
蓝牙适配器选择的连接间隔:30 by
从延迟:0包
监控超时:720 23(断开连接前23丢失数据包)
Android 5.0.1 Nexus 4上的Lollipop
操作系统允许的间隔:30-50 OS
蓝牙适配器选择的连接间隔: 48.75ms
从延迟:0包
监控超时:2000 41(断开连接前41丢失数据包)
带有外部适配器的OSX10.10.1 (Apple蓝牙软件版本: 4.3.1f2 15015):
操作系统允许的间隔:未知
蓝牙适配器选择的连接间隔:15 by
从延迟:0包
监控超时:2000 133(断开连接前133个丢失数据包)
这就解释了为什么我与Livescribe笔的连接在Linux上不那么可靠。内核默认的做法是在只丢失6个数据包之后删除连接,而pen从不推荐更好的参数。
在Linux3.17及更高版本上,可以通过写入/sys/kernel/debug/bluetooth/hci0/supervision_timeout.来调整监视超时
测试方法: Linux上的跟踪是使用hcidump (在Android中的开发人员选项中)获得的,并在Wireshark中为HCI创建连接命令进行了分析。利用TI公司的包嗅探器软件,利用TI CC2540获得了OSX和CC2540的踪迹。
https://stackoverflow.com/questions/24945620
复制相似问题