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

Python Socket客户端崩溃求助:连接建立后无响应且断开

问题描述

启动服务器后启动客户端,服务器能接收数据,但客户端无法获取响应并崩溃,报错信息如下:

data = sock.recv(1024)
ConnectionAbortedError: [WinError 10053] 你的主机中的软件中止了一个已建立的连接。

服务端代码
import pygame, socket, time
pygame.init()

main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
main_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
main_socket.bind(("localhost", 10000))
main_socket.setblocking(0)
main_socket.listen(5)

players_sockets = []


while True:
    
    try:
        new_socket, addr = main_socket.accept()
        print("Connect", addr)
        new_socket.setblocking(0)
        players_sockets.append(new_socket)
    except:
        pass

    
    for i in players_sockets:
        try:
            data = i.recv(1024)
            data = data.decode()
        except:
            pass 

    for i in players_sockets:
        try:
                 i.send("server data").encode()
        except:
            players_sockets.remove(i)
            print("Disconnect")
            i.close()
    
    time.sleep(1)
客户端代码
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.connect(("localhost", 10000))

while True:

    sock.send("Command".encode())

    data = sock.recv(1024)
    data = data.decode()

    print(data)
问题原因及修复方案

核心问题1:服务端发送数据的语法错误

服务端中i.send("server data").encode()是错误写法:应该先对字符串编码再发送,正确格式为i.send("server data".encode())。原代码会直接尝试发送未编码的字符串,触发异常后服务端会关闭客户端连接,这就是客户端收到连接中止错误的直接原因。

核心问题2:遍历列表时修改列表引发的异常

服务端在for i in players_sockets:循环中直接执行players_sockets.remove(i),会破坏列表的遍历结构,导致后续遍历出错,可能误删其他连接或引发索引异常。

核心问题3:非阻塞Socket的异常处理不严谨

服务端使用非阻塞Socket,recv在没有数据时会抛出BlockingIOError,原代码捕获所有异常但未区分情况;当客户端主动断开时,recv会返回空字节串,原代码未处理该场景,导致无效连接残留。


修复后的服务端代码

import pygame, socket, time
pygame.init()

main_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
main_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
main_socket.bind(("localhost", 10000))
main_socket.setblocking(0)
main_socket.listen(5)

players_sockets = []


while True:
    # 处理新连接:仅捕获无新连接的BlockingIOError
    try:
        new_socket, addr = main_socket.accept()
        print("Connect", addr)
        new_socket.setblocking(0)
        players_sockets.append(new_socket)
    except BlockingIOError:
        pass

    # 处理接收数据:遍历列表副本避免修改原列表
    for sock in players_sockets.copy():
        try:
            data = sock.recv(1024)
            if not data:  # 客户端断开时recv返回空
                players_sockets.remove(sock)
                sock.close()
                print("Disconnect (client closed)")
                continue
            data = data.decode()
            print(f"Received from client: {data}")
        except BlockingIOError:
            pass  # 无数据时忽略
        except Exception as e:
            # 其他异常,移除并关闭连接
            players_sockets.remove(sock)
            sock.close()
            print(f"Disconnect: {str(e)}")

    # 处理发送数据:遍历列表副本,先编码再发送
    for sock in players_sockets.copy():
        try:
            sock.send("server data".encode())
        except Exception as e:
            players_sockets.remove(sock)
            sock.close()
            print(f"Disconnect (send failed): {str(e)}")
    
    time.sleep(1)

客户端代码优化(可选,避免无提示崩溃)

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
try:
    sock.connect(("localhost", 10000))
except Exception as e:
    print(f"连接服务器失败: {str(e)}")
    exit()

while True:
    try:
        sock.send("Command".encode())
        data = sock.recv(1024)
        if not data:
            print("服务器已断开连接")
            break
        data = data.decode()
        print(data)
    except Exception as e:
        print(f"客户端错误: {str(e)}")
        break
sock.close()

内容的提问来源于stack exchange,提问作者MrBelor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:01:37