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

Python Socket客户端运行报[WinError 10053]连接被主机软件中止错误

问题背景

运行环境为Python 3.10、Windows 10 64位,开发游戏配套Socket通信客户端与服务端时,服务端运行无报错,但客户端启动后触发ConnectionAbortedError: [WinError 10053],错误提示为:

An established connection was aborted by the software in your host machine

完整错误回溯:

Traceback (most recent call last):
  File "C:\Users\---\Desktop\---\---\testClient.py", line 19, in <module>
    data = s.recv(1024)
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

附原始问题代码:

原始server.py代码

import socket
import sys
import threading
import os
import random as rand
HOST = ''  
PORT = 7474
os.system('title GunLord server vBETA')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('# Socket created')
try:
    s.bind((HOST, PORT))
except socket.error as msg:
    print('# Bind failed. ')
    sys.exit()

print('# Socket bind complete')
s.listen(100)
print('# Socket now listening')

def clientThread(conn, addr, playerID):
    global PlayerLocationData
    print('# Connected to ' + addr[0] + ':' + str(addr[1]))
    try:
        while True:
            data = conn.recv(1024)
            line = data.decode('UTF-8')
            clientData = line.split('&')
            PlayerLocationData[playerID] = str(clientData[0]) +'.'+str(clientData[1])+'.'+str(clientData[2])
            responsePlayerLocationData = ''
            for i in range(len(PlayerLocationData)):
                responsePlayerLocationData +=PlayerLocationData[i]+'%%'
            try:
                conn.send(str(responsePlayerLocationData).encode())
            except:
                PlayerLocationData[playerID] = None
    except:
        conn.close()
threads = []
global PlayerLocationData
PlayerLocationData = []
while True:
    conn, addr = s.accept()
    playerID = rand.randint(1, 1000)
    t = threading.Thread(target=clientThread(conn, addr, playerID))
    t.start()
    threads.append(t)


s.close()

原始client.py代码

import socket
import random as rand
import time as t
host = '127.0.0.1'
port = 7474
s = socket.socket()
s.connect((host, port))
global PlayerLocations
PlayerLocations = []
def recvDecoder(recvText):
    global PlayerLocations
    PlayerLocations = recvText.split('%%')
while True:
    testX = rand.randint(1, 10)
    testY = rand.randint(1, 10)
    testZ = rand.randint(1, 10)
    print('test coords: {}, {}, {}' .format(testX, testY, testZ))
    s.send('{}&{}&{}'.format(testX, testY, testZ).encode())
    data = s.recv(1024)
    line = data.decode('UTF-8')
    recvDecoder(line)
    t.sleep(.3)
错误原因

共3个核心问题直接触发连接被服务端主动关闭:

  1. 线程创建写法完全错误:原代码写target=clientThread(conn, addr, playerID)时,会在主线程直接同步执行clientThread函数,根本没有创建新的子线程。主线程会直接阻塞在客户端处理循环里,外层的accept逻辑完全无法运行,只要函数内触发任何异常,就会直接关闭连接。
  2. 列表索引越界触发异常断连:PlayerLocationData初始化为空列表,却用1~1000的随机数作为索引直接赋值,Python列表不支持对超出当前长度的索引直接赋值,第一次收到客户端坐标数据执行赋值操作时就会抛出IndexError,直接进入except块执行conn.close(),客户端侧就会收到连接被中止的错误。
  3. 附加逻辑缺陷:playerID用无去重的随机数生成,多客户端连接时会出现ID冲突、位置数据互相覆盖的问题;没有处理recv返回空字节(对端正常断开)的场景,会触发解码异常。
修复方案

按以下步骤修改代码即可解决问题:

  • 修正线程创建语法:target参数只传函数引用,函数参数通过args参数以元组形式传入,不要直接在target位置调用函数。
  • 将PlayerLocationData从列表改为字典,不需要连续索引即可存储任意playerID对应的位置数据,彻底避免索引越界问题。
  • 增加playerID去重逻辑,确保每个连接的玩家ID唯一。
  • 增加recv空值判断,收到空数据时主动退出连接循环,清理对应玩家的位置数据。

修复后server.py代码

import socket
import sys
import threading
import os
import random as rand

HOST = ''  
PORT = 7474
os.system('title GunLord server vBETA')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('# Socket created')
try:
    s.bind((HOST, PORT))
except socket.error as msg:
    print('# Bind failed. ')
    sys.exit()

print('# Socket bind complete')
s.listen(100)
print('# Socket now listening')

# 改用字典存储玩家位置,避免列表索引越界
PlayerLocationData = {}
used_player_ids = set()

def clientThread(conn, addr, playerID):
    global PlayerLocationData
    print('# Connected to ' + addr[0] + ':' + str(addr[1]) + f', playerID: {playerID}')
    try:
        while True:
            data = conn.recv(1024)
            # 处理对端断开的情况
            if not data:
                break
            line = data.decode('UTF-8')
            clientData = line.split('&')
            # 过滤长度不对的非法数据包
            if len(clientData) <3:
                continue
            PlayerLocationData[playerID] = f"{clientData[0]}.{clientData[1]}.{clientData[2]}"
            responsePlayerLocationData = ''
            # 遍历字典拼接所有玩家位置
            for pos in PlayerLocationData.values():
                responsePlayerLocationData += pos +'%%'
            conn.send(responsePlayerLocationData.encode())
    except Exception as e:
        print(f"Connection with {addr} error: {e}")
    finally:
        # 清理断开连接的玩家数据,关闭连接
        if playerID in PlayerLocationData:
            del PlayerLocationData[playerID]
        used_player_ids.remove(playerID)
        conn.close()
        print(f"# Disconnected from {addr[0]}:{addr[1]}, playerID: {playerID}")

threads = []
while True:
    conn, addr = s.accept()
    # 生成不重复的playerID
    while True:
        playerID = rand.randint(1, 1000)
        if playerID not in used_player_ids:
            used_player_ids.add(playerID)
            break
    # 修正线程传参写法,不要直接调用目标函数
    t = threading.Thread(target=clientThread, args=(conn, addr, playerID))
    t.daemon = True
    t.start()
    threads.append(t)

s.close()

修复后client.py代码(增加断连异常捕获)

import socket
import random as rand
import time as t

host = '127.0.0.1'
port = 7474
s = socket.socket()
s.connect((host, port))
PlayerLocations = []

def recvDecoder(recvText):
    global PlayerLocations
    # 过滤末尾空字符串
    PlayerLocations = [pos for pos in recvText.split('%%') if pos]

try:
    while True:
        testX = rand.randint(1, 10)
        testY = rand.randint(1, 10)
        testZ = rand.randint(1, 10)
        print('test coords: {}, {}, {}' .format(testX, testY, testZ))
        s.send(f'{testX}&{testY}&{testZ}'.encode())
        data = s.recv(1024)
        if not data:
            print("Server closed connection")
            break
        line = data.decode('UTF-8')
        recvDecoder(line)
        print(f"All player locations: {PlayerLocations}")
        t.sleep(.3)
except Exception as e:
    print(f"Connection error: {e}")
finally:
    s.close()

修改后重新运行服务端和客户端即可正常通信,不会再触发10053错误。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 05:45:42