WinError 10038错误排查:MediaPipe向Unity传输姿态数据失败
TCP Socket连接报错WinError 10038:尝试对非套接字执行操作
我在尝试通过TCP Socket将MediaPipe姿态估计的数据发送到Unity时,客户端出现WinError 10038错误(尝试对非套接字执行操作)。以下是客户端Python代码和服务器端Unity C#代码:
客户端Python代码
import socket import PoseEstimation as pm import cv2 host, port = "127.0.0.1", 25001 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) cap = cv2.VideoCapture(0) detector = pm.PoseEstimatior() def sendData(lmString, sock, host, port): #sock.connect((host, port)) sock.send(lmString.encode("utf-8")) response = sock.recv(1024).decode("utf-8") print(response) #sock.close() while cap.isOpened(): _, img = cap.read() img = detector.findPose(img) lmList, complete = detector.getPosition(img) lmString = ','.join([','.join(map(str, inner_list)) for inner_list in lmList]) if complete: sendData(lmString, sock, host, port) cv2.imshow("Image", img) if cv2.waitKey(1) == ord('q'): break sock.close() cap.release() cv2.destroyAllWindows()
服务器端Unity C#代码
using System.Net; using System.Net.Sockets; using System.Text; using UnityEngine; using System.Threading; using System.Linq; public class MyListener : MonoBehaviour { Thread thread; public int connectionPort = 25001; TcpListener server; TcpClient client; bool running; public GameObject[] Body; Vector3[] position = Enumerable.Repeat(Vector3.zero, 33).ToArray(); void Start() { // 单独线程接收数据,避免Unity卡顿 ThreadStart ts = new ThreadStart(GetData); thread = new Thread(ts); thread.Start(); } void GetData() { // 创建服务器 server = new TcpListener(IPAddress.Any, connectionPort); server.Start(); // 获取客户端连接 client = server.AcceptTcpClient(); // 开始监听 running = true; while (running) { Connection(); } server.Stop(); } void Connection() { // 读取网络流数据 NetworkStream nwStream = client.GetStream(); byte[] buffer = new byte[client.ReceiveBufferSize]; int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize); // 解码为字符串 string dataReceived = Encoding.UTF8.GetString(buffer, 0, bytesRead); // 过滤空字符串 if (dataReceived != null && dataReceived != "") { // 解析数据格式 position = ParseData(dataReceived); nwStream.Write(buffer, 0, bytesRead); } } // 自定义数据解析函数,需匹配发送端格式 public static Vector3[] ParseData(string dataString) { Debug.Log(dataString); // 分割数据为数组 string[] stringArray = dataString.Split(','); Vector3[] vectors = new Vector3[33]; for (int i = 0; i < 33; i++) { float x = float.Parse(stringArray[1 + (i * 4)]) / 100; float y = float.Parse(stringArray[2 + (i * 4)]) / 100; float z = float.Parse(stringArray[3 + (i * 4)]) / 100; vectors[i] = new Vector3(x, y, z); } return vectors; } void Update() { // 更新场景中物体位置 for (int i = 0; i < 33; i++) { Body[i].transform.localPosition = position[i]; } } }
错误原因及修复方案
WinError 10038本质是操作了失效的套接字对象,以下是针对性修复:
客户端添加连接异常处理
当服务器断开连接时,客户端套接字会失效,需捕获异常并重新连接:def sendData(lmString, sock, host, port): try: sock.send(lmString.encode("utf-8")) response = sock.recv(1024).decode("utf-8") print(response) except (BrokenPipeError, ConnectionResetError, socket.error) as e: print(f"连接失效,重新连接: {e}") sock.close() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) sock.send(lmString.encode("utf-8")) response = sock.recv(1024).decode("utf-8") print(response) return sock # 主循环中更新套接字对象 if complete: sock = sendData(lmString, sock, host, port)服务器端优化连接逻辑
当前服务器仅处理一次连接,断开后无法重新接收,需修改为循环等待新连接:void GetData() { server = new TcpListener(IPAddress.Any, connectionPort); server.Start(); running = true; while (running) { try { client = server.AcceptTcpClient(); while (running && client.Connected) { Connection(); } } catch (SocketException) { client?.Close(); } } server.Stop(); } void Connection() { if (!client.Connected) return; try { NetworkStream nwStream = client.GetStream(); if (!nwStream.CanRead) return; byte[] buffer = new byte[client.ReceiveBufferSize]; int bytesRead = nwStream.Read(buffer, 0, client.ReceiveBufferSize); if (bytesRead <= 0) { client.Close(); return; } string dataReceived = Encoding.UTF8.GetString(buffer, 0, bytesRead); if (!string.IsNullOrEmpty(dataReceived)) { position = ParseData(dataReceived); nwStream.Write(buffer, 0, bytesRead); } } catch (IOException) { client.Close(); } }验证数据格式一致性
确保MediaPipe输出的姿态数据符合服务器解析逻辑(33个关键点,每个点4个数值),避免因数据错误导致连接中断:lmString = ','.join([','.join(map(str, inner_list)) for inner_list in lmList]) # 验证数据段数量是否为33*4=132 if len(lmString.split(',')) == 132 and complete: sock = sendData(lmString, sock, host, port) else: print("姿态数据格式错误,跳过发送")
内容的提问来源于stack exchange,提问作者YanHem
相关产品推荐
相关产品推荐

