【发布时间】:2021-04-20 20:08:56
【问题描述】:
我编写了一个 Python 程序,它通过蓝牙套接字(参见下面的示例)读取和写入 L2CAP 连接以与某些硬件通信。但是,代码可能希望为蓝牙适配器处理太多的 IO,因此我将其配备为通过在需要时减慢 bar 循环来处理滞后的读取和写入,因为这比在响应请求时延迟更可取。
sock = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, socket.BTPROTO_L2CAP)
sock.connect((bt_addr, bt_port))
sock.setblocking(False)
stall_loop = asyncio.Event()
stall_loop.set()
async def bar():
while True:
await stall_loop.wait()
await loop.sock_sendall(generate_data(time.time()))
await asyncio.sleep(maybe_to_small_delay)
async def foo():
while True:
await request = loop.sock_recv(sock, 400)
stall_loop.clear()
await loop.sock_sendall(generate_response(request))
stall_loop.set()
asyncio.gather(foo, bar)
但问题是,在bar 一次冻结几秒钟之前,这些循环都没有看到任何明显的减速。
我使用time.time() 对两个循环的执行进行计时,执行时间只有毫秒,包括 IO(bar 冻结时除外),但foo 写入的任何内容都只能延迟 15 秒发送(由tshark 报告并与python 认为写入完成的时间进行比较)
我想要的行为是仅在实际传输数据后才返回写入,以便保持响应 foo 和 bar 尽可能接近所需速度。
我认为罪魁祸首是某种缓冲策略,它会缓冲大量数据,直到缓冲区已满,然后将其完全刷新。我怎样才能禁用此 bahviour 和/或将缓冲区大小限制为例如2包?我在 ioctl 上找不到 bluez 的文档。
版本:
- 内核 5.10.17-vl7+ 上的 Raspbian
- Python 3.7.3
- bluez 5.50
【问题讨论】:
-
@ukBaz,我想到了,但遗憾的是他们不支持蓝牙插座。它们都是 Opening Network Connection API 的包装器,仅支持
AF_INET、AF_INET6和AF_UNIX使用附加功能。 -
@ukBaz 所以你的意思是我应该像上面那样创建套接字,然后用一个小缓冲区将它包装在
Stream中。这不会造成更多的延迟,因为套接字本身已经滞后并且 Stream 缓冲区也是如此,或者 Streams 是否对我不了解的套接字有一些了解并配置套接字的缓冲?
标签: python sockets bluetooth python-asyncio bluez