PyBluez调用accept()报[Errno 77]错误如何解决
问题根因
[Errno 77] File descriptor in bad state 报错的核心原因是混淆了RFCOMM蓝牙套接字的客户端、服务端角色的API调用逻辑:
- 调用
s.connect()后,当前套接字会被初始化为主动发起连接的客户端套接字,仅用于和远端设备直接通信,不存在监听等待新连接的状态,无法调用accept()方法。 accept()是服务端监听套接字专属方法,只有套接字完成本地端口绑定、开启监听,进入等待接入状态后,才能合法调用accept()接收新的连接请求。
分场景正确实现
场景1:树莓派作为客户端主动连接手机
该场景不需要调用accept(),connect()执行成功后,直接使用当前套接字即可和手机收发数据,示例代码:
import bluetooth # 替换为手机的实际蓝牙MAC地址 target_mac = "XX:XX:XX:XX:XX:XX" port = 19 s = bluetooth.BluetoothSocket(bluetooth.RFCOMM) s.connect((target_mac, port)) # 连接建立后直接通过s收发数据 s.send("hello from raspberry pi".encode("utf-8")) data = s.recv(1024) print(f"收到手机返回数据: {data.decode('utf-8')}") s.close()
注意:该模式需要手机端提前在对应RFCOMM端口开启蓝牙服务监听,否则会触发连接拒绝错误。
场景2:树莓派作为服务端等待手机主动连接
该场景才需要使用accept(),完整流程为创建套接字、绑定本地端口、开启监听、等待连接,示例代码:
import bluetooth port = 19 # 创建服务端套接字 server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) # 绑定本地蓝牙适配器的对应端口 server_sock.bind(("", port)) # 开启监听,设置最大排队连接数为1 server_sock.listen(1) print(f"蓝牙服务已启动,在RFCOMM端口{port}等待设备连接...") # 等待客户端接入,此处调用accept为合法操作 client_sock, client_addr = server_sock.accept() print(f"已接入设备地址: {client_addr}") # 通过返回的client_sock和连接的手机收发数据 client_sock.send("hello from raspberry pi server".encode("utf-8")) data = client_sock.recv(1024) print(f"收到手机数据: {data.decode('utf-8')}") client_sock.close() server_sock.close()
额外排查点
调整套接字逻辑后如果仍然报错,按以下顺序排查:
- 先通过
bluetoothctl确认树莓派蓝牙已启动、可被发现,且已经和目标手机完成配对 - 确认使用的RFCOMM端口和对端开放的端口一致:通用蓝牙串口(SPP)服务默认端口为1,使用19这类自定义端口需要提前确认对端对应端口已开启监听
- 确认运行代码的用户具备蓝牙操作权限,可先通过
sudo执行代码排除权限干扰
内容的提问来源于stack exchange,提问作者Mihai
相关产品推荐
相关产品推荐

