You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyGame:接收Socket停止消息后停止多边形移动并保留画面

问题根源与解决方案

核心问题

你的服务端代码存在两个致命错误,导致收到消息后脚本直接崩溃:

  1. 错误地对监听套接字调用recv():server_socket是用于监听新连接的套接字,当select检测到它可读时,意味着有新客户端发起连接请求,此时必须调用accept()获取实际的通信套接字,而非直接调用recv()。直接对监听套接字执行recv()会触发异常,导致脚本终止。
  2. 未处理客户端连接断开的情况:即使正确获取了客户端套接字,当客户端发送数据后关闭连接,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 17:18:22