Socket连接双向切换循环实现求助:现有代码阻塞问题排查
解决方案:基于Select的非阻塞双向通信
核心思路
用select.select()(Python)或select()(C)同时监听标准输入和Socket连接的可读事件,避免单线程下的阻塞问题,实现用户输入与Socket消息的双向切换处理。
BeagleBone Black 服务端代码(Python)
import socket import select import sys def main(): # 创建Socket并配置 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定BBB的IP与端口(替换为你的BBB实际IP) server_address = ('0.0.0.0', 8888) server_socket.bind(server_address) server_socket.listen(1) print("等待电脑客户端连接...") # 接受客户端连接 client_socket, client_addr = server_socket.accept() print(f"已连接:{client_addr}") # 监听列表:标准输入 + 客户端Socket inputs = [sys.stdin, client_socket] try: while True: # 等待可读事件触发 readable, _, _ = select.select(inputs, [], []) for sock in readable: if sock == sys.stdin: # 处理本地用户输入,发送给电脑客户端 user_input = sys.stdin.readline().strip() if user_input.lower() == 'quit': print("退出程序") client_socket.sendall(user_input.encode('utf-8')) break client_socket.sendall(user_input.encode('utf-8')) elif sock == client_socket: # 处理电脑端发来的消息 data = sock.recv(1024) if not data: print("客户端断开连接") break print(f"收到电脑消息:{data.decode('utf-8')}") else: continue break finally: client_socket.close() server_socket.close() if __name__ == "__main__": main()
电脑客户端代码(Python)
import socket import select import sys def main(): # 连接BBB服务端(替换为你的BBB实际IP) client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) bbb_address = ('192.168.7.2', 8888) client_socket.connect(bbb_address) print("已连接到BeagleBone Black") # 监听列表:标准输入 + BBB Socket inputs = [sys.stdin, client_socket] try: while True: readable, _, _ = select.select(inputs, [], []) for sock in readable: if sock == sys.stdin: # 处理本地用户输入,发送给BBB user_input = sys.stdin.readline().strip() if user_input.lower() == 'quit': print("退出程序") client_socket.sendall(user_input.encode('utf-8')) break client_socket.sendall(user_input.encode('utf-8')) elif sock == client_socket: # 处理BBB发来的消息 data = sock.recv(1024) if not data: print("服务端断开连接") break print(f"收到BBB消息:{data.decode('utf-8')}") else: continue break finally: client_socket.close() if __name__ == "__main__": main()
关键说明
select函数会阻塞直到监听的文件描述符中有可读事件,既不会卡在等待用户输入,也不会卡在等待Socket消息。- 当用户输入回车或Socket收到消息时,对应描述符会被标记为可读,进入对应处理分支。
- 输入
quit可触发双方退出并断开连接。
C语言版本核心逻辑(适用于BBB原生开发)
- 初始化
fd_set集合,加入STDIN_FILENO和Socket文件描述符。 - 循环调用
select(),判断哪个描述符可读。 - 分别处理标准输入读取(
read(STDIN_FILENO, ...))和Socket接收(recv(...))。
排查要点
- 确保BBB与电脑在同一局域网,IP地址配置正确。
- 关闭双方防火墙或开放指定端口(如8888)。
- 统一使用UTF-8编码处理文本,避免乱码。
内容的提问来源于stack exchange,提问作者Munix0
相关产品推荐
相关产品推荐

