PyBluez蓝牙Socket连接数小时后莫名中断,寻求解决方案
蓝牙Socket长连接数小时后中断问题
环境与现象
- 服务端:Ubuntu 22.04 迷你PC,基于PyBluez开发
- 客户端:2台RPi 4,同样使用PyBluez实现
- 异常表现:初始数据传输正常,运行数小时后传输中断;蓝牙系统连接状态显示正常,但程序停止收发日志;重启程序无法恢复,仅重启服务端PC能暂时解决;已排除缓冲区溢出、CPU/内存占用过高问题。
相关代码片段
服务端客户端处理线程
# thread for each client connection def handle_client(connection): while True: try: data = connection.recv(1024).decode('utf-8') if not data: break reply = f'Received from {str(connection)}' connection.sendall(reply) except Exception as e: print(str(e)) connection.close() connection.close() ...
客户端循环逻辑
... while True: try: data = MacAddr #MacAddr obtained using subprocess conn.sendall(data + '\n') res = conn.recv(1024).decode('utf-8') except Exception as e: # attempt to reconnect to server ... ...
问题定位与解决方案
核心问题推测
- PyBluez底层资源泄漏:服务端异常处理仅关闭连接,未确保线程正常退出,导致系统蓝牙资源被耗尽,无法维持现有连接或处理新请求。
- 静默链路失效未检测:蓝牙连接状态显示正常,但实际链路已静默断开,
recv()调用无限阻塞,导致线程挂起,停止处理数据。 - 半开连接未清理:客户端意外断开后,服务端
recv()持续阻塞,占用线程资源,累积后导致服务端无响应。
具体修复方案
完善服务端线程与超时处理
给recv()设置超时,避免无限阻塞,同时确保异常后线程正常退出:import socket def handle_client(connection): # 设置30秒接收超时,避免无限阻塞 connection.settimeout(30) try: while True: try: data = connection.recv(1024).decode('utf-8') if not data: break reply = f'Received from {str(connection)}' connection.sendall(reply) except socket.timeout: # 超时发送心跳包检测链路 connection.sendall(b'HEARTBEAT') continue except Exception as e: print(f"Client error: {str(e)}") break finally: connection.close() print(f"Closed connection: {str(connection)}")添加双向心跳机制
- 客户端:每固定周期发送心跳包,若连续3次未收到服务端响应,触发重连逻辑
- 服务端:收到心跳包立即回复,若连续3个周期未收到客户端心跳,主动断开连接并清理资源
优化服务端连接管理
- 维护活跃连接列表,定期遍历检查连接状态
- 使用线程池(如
concurrent.futures.ThreadPoolExecutor)管理客户端线程,避免无限制创建线程耗尽资源
调整系统蓝牙配置
修改Ubuntu服务端/etc/bluetooth/main.conf,添加以下配置防止链路休眠:AutoEnable=true DiscoverableTimeout=0 PairableTimeout=0重启蓝牙服务:
sudo systemctl restart bluetooth升级或替换PyBluez
PyBluez对现代蓝牙协议的支持存在兼容性问题,可尝试升级到最新版本,或改用bleak(针对BLE场景)、原生蓝牙Socket结合bluetoothctl的实现方式。
内容的提问来源于stack exchange,提问作者baeksangyeol
相关产品推荐
相关产品推荐

