Python脚本传输桌面画面至Unity时遇WinError 10053连接中止问题
解决ConnectionAbortedError 10053的问题
核心问题分析
出现ConnectionAbortedError: [WinError 10053]的主要原因包括:
- 字节序不匹配:Python用大端序发送帧长度,Unity默认用系统小端序解析,导致帧大小计算错误,引发数据读取异常
- Unity端内存泄漏:每次接收帧都创建新
Texture2D,未回收旧资源,长期运行导致性能下降 - 发送频率过高:Python无间隔发送帧,Unity处理速度跟不上,导致网络缓冲区溢出
- 异常处理不完整:两端未处理连接断开等异常,导致资源未正确释放
修复后的代码
Python服务端
import socket import cv2 import numpy as np from PIL import ImageGrab import time # Set up the server server_ip = 'Insert IP Here' server_port = Insert Port Here # Create a socket object server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Bind the socket to the address server_socket.bind((server_ip, server_port)) # Listen for incoming connections server_socket.listen(1) print("Waiting for Unity application to connect...") # Accept incoming connection connection, address = server_socket.accept() print("Connected to Unity application at", address) # Function to capture desktop frames and send them over the network def send_frames(): try: while True: # Capture desktop frame frame = capture_screen() # 统一用小端序发送帧长度,和Unity端匹配 frame_size = len(frame) connection.sendall(frame_size.to_bytes(4, byteorder='little')) # Send frame data connection.sendall(frame) # 控制发送频率,避免Unity处理不过来(比如30帧/秒) time.sleep(1/30) except (KeyboardInterrupt, ConnectionResetError, BrokenPipeError): print("Connection closed.") finally: connection.close() server_socket.close() def capture_screen(): # Capture desktop screen using OpenCV screen = cv2.cvtColor(np.array(ImageGrab.grab()), cv2.COLOR_RGB2BGR) # 降低JPG质量,减少传输数据量(可根据需求调整,0-100) _, frame_encoded = cv2.imencode('.jpg', screen, [int(cv2.IMWRITE_JPEG_QUALITY), 70]) return frame_encoded.tobytes() if __name__ == "__main__": send_frames()
Unity客户端
using UnityEngine; using System; using TMPro; using System.Net.Sockets; using System.Threading.Tasks; public class ScreenMirror : MonoBehaviour { public Material planeMaterial; public string serverIp = "Insert IP Here"; public int serverPort = Insert Port Here; public TMP_Text networkStatusText; private TcpClient client; private NetworkStream stream; private bool receiving = false; private const int bufferSize = 1024 * 1024; // 1 MB buffer size private Texture2D texture; // 复用Texture2D,避免内存泄漏 private async void Start() { try { client = new TcpClient(); await client.ConnectAsync(serverIp, serverPort); stream = client.GetStream(); receiving = true; networkStatusText.text = "Connected"; // 初始化Texture2D texture = new Texture2D(1, 1); // Start receiving frames asynchronously await ReceiveFramesAsync(); } catch (Exception e) { Debug.LogError("Error connecting to server: " + e.Message); networkStatusText.text = "Error: " + e.Message; } } private async Task ReceiveFramesAsync() { try { byte[] buffer = new byte[bufferSize]; while (receiving) { // Read frame size int bytesRead = await stream.ReadAsync(buffer, 0, 4); if (bytesRead != 4) { Debug.LogWarning("Incomplete frame size received."); break; } // 用小端序解析帧长度,和Python端匹配 int frameSize = BitConverter.ToInt32(buffer, 0); // 检查帧大小是否超过缓冲区限制 if (frameSize > bufferSize) { Debug.LogError($"Frame size {frameSize} exceeds buffer size {bufferSize}"); break; } // Read frame data bytesRead = 0; while (bytesRead < frameSize) { int read = await stream.ReadAsync(buffer, bytesRead, frameSize - bytesRead); if (read == 0) { Debug.LogWarning("Connection closed by server."); break; } bytesRead += read; } if (bytesRead != frameSize) break; // 复用Texture2D加载图片 if (!texture.LoadImage(buffer)) { Debug.LogWarning("Failed to load image data."); continue; } // Apply texture to plane material planeMaterial.mainTexture = texture; } } catch (Exception e) { Debug.LogError("Error receiving frames: " + e.Message); networkStatusText.text = "Error: " + e.Message; } finally { receiving = false; if (stream != null) stream.Close(); if (client != null) client.Close(); // 释放Texture资源 if (texture != null) Destroy(texture); networkStatusText.text = "Disconnected"; } } private void OnDestroy() { receiving = false; } }
额外建议
- 确保Python和Unity使用相同的IP和端口,测试时优先用
127.0.0.1(本地回环)排除网络问题 - 关闭Python和Unity程序后,检查端口是否被占用(可用
netstat -ano | findstr 端口号命令) - 若仍有问题,暂时关闭防火墙测试(测试后再恢复规则)
内容的提问来源于stack exchange,提问作者thePrnvBot
相关产品推荐
相关产品推荐

