PyGame:接收Socket停止消息后停止多边形移动并保留画面
问题根源与解决方案
核心问题
你的服务端代码存在两个致命错误,导致收到消息后脚本直接崩溃:
- 错误地对监听套接字调用
recv():server_socket是用于监听新连接的套接字,当select检测到它可读时,意味着有新客户端发起连接请求,此时必须调用accept()获取实际的通信套接字,而非直接调用recv()。直接对监听套接字执行recv()会触发异常,导致脚本终止。 - 未处理客户端连接断开的情况:即使正确获取了客户端套接字,当客户端发送数据后关闭连接,
recv()会返回空字节串b'',若不处理该情况,后续逻辑会出现异常。
修正后的服务端代码
import pygame import select import socket # 初始化Pygame并创建窗口 pygame.init() screen = pygame.display.set_mode((640, 480)) # 初始化背景色,避免绘制叠加残留 screen.fill((255, 255, 255)) # 配置Socket服务端 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('192.168.178.49', 5000)) server_socket.listen(1) # 维护需要监听的套接字列表:监听套接字 + 已连接客户端套接字 inputs = [server_socket] # 存储客户端连接信息 client_connections = {} # 多边形初始化 triangle_pos = [0, 10] triangle_speed = 1 stop_movement = False # 主循环 exiting = False while not exiting: # 监听套接字可读事件(新连接或消息) readable, _, _ = select.select(inputs, [], [], 0.1) for sock in readable: if sock is server_socket: # 处理新客户端连接 client_sock, client_addr = sock.accept() inputs.append(client_sock) client_connections[client_sock] = client_addr else: # 接收客户端消息 data = sock.recv(1024) if data == b'stop': stop_movement = True elif data == b'': # 客户端断开连接,清理资源 inputs.remove(sock) del client_connections[sock] sock.close() else: stop_movement = False # 更新多边形位置(未停止时) if not stop_movement: triangle_pos[0] += triangle_speed if triangle_pos[0] > 640: triangle_pos[0] = 0 # 清空屏幕避免轨迹残留 screen.fill((255, 255, 255)) # 绘制多边形 pygame.draw.polygon( screen, (255, 0, 0), [ (triangle_pos[0], triangle_pos[1]), (triangle_pos[0]+5, triangle_pos[1]+10), (triangle_pos[0]-5, triangle_pos[1]+10) ] ) # 更新显示 pygame.display.flip() # 处理窗口关闭事件 for event in pygame.event.get(): if event.type == pygame.QUIT: exiting = True # 关闭所有套接字 for sock in inputs: sock.close() # 退出Pygame pygame.quit()
关键修正点
- 分离监听与通信套接字:通过判断可读套接字是否为监听套接字,分别处理新连接和消息接收逻辑,避免对监听套接字执行
recv()操作。 - 处理客户端断开:当
recv()返回空字节串时,及时移除并关闭客户端套接字,防止无效连接导致的异常。 - 添加背景清空:每次绘制前用背景色填充屏幕,既避免多边形移动留下轨迹,也能在停止后清晰保留当前位置的显示。
客户端代码(可选优化)
客户端发送消息后主动关闭连接,确保服务端能正确识别断开事件:
import socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect(('192.168.178.49', 5000)) client_socket.send(b'stop') client_socket.close()
内容的提问来源于stack exchange,提问作者Bigfoot99
相关产品推荐
相关产品推荐

