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

Hololens 2模拟器Unity TCP连接问题:Socket连接正常但无数据传输

HoloLens 2模拟器Unity应用与Python脚本TCP连接异常排查

问题现象

Python端socket.connect(server_address)和sock.sendall(message)执行正常,但模拟器端Unity代码卡在using (connectedTcpClient = tcpListener.AcceptTcpClient()),后续断点及打印逻辑均无响应。

已尝试的排查操作

  • 在运行模拟器的本机执行Python脚本,将IP改为127.0.0.1/localhost,问题依旧;
  • 将脚本中的IP替换为模拟器IP,无法建立连接;
  • Unity播放器设置已勾选InternetClient、InternetClientServer和PrivateNetworkClientServer;
  • 已按照微软官方指南配置模拟器TCP服务器端口。

代码片段

Python脚本

import socket
import sys

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port where the server is listening
server_address = ('192.168.1.152', 9090)
print('connecting to {} port {}...'.format(*server_address))
sock.connect(server_address)

try:
    # Send data
    message = b'Hello World!'
    print('sending {!r}'.format(message))
    sock.sendall(message)
    print('message sent, waiting...')

    # Look for the response
    amount_received = 0
    amount_expected = len(message)

    while amount_received < amount_expected:
        data = sock.recv(16)
        amount_received += len(data)
        print('received {!r}'.format(data))

finally:
    print('closing socket')
    sock.close()

Unity C#代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using TMPro;
using UnityEngine;
using UnityEngine.UIElements;

public class TCPyManager : MonoBehaviour
{
    #region private members     
    /// <summary>   
    /// TCPListener to listen for incoming TCP connection   
    /// requests.   
    /// </summary>  
    private TcpListener tcpListener;
    /// <summary> 
    /// Background thread for TcpServer workload.   
    /// </summary>  
    private Thread tcpListenerThread;
    /// <summary>   
    /// Create handle to connected tcp client.  
    /// </summary>  
    private TcpClient connectedTcpClient;

    private string clientMessage;
    private string status;
    private string data;

    public TMP_Text statusText;
    public TMP_Text dataText;

    #endregion

    // Use this for initialization
    void Start()
    {
        // Start TcpServer background thread        
        tcpListenerThread = new Thread(new ThreadStart(ListenForIncomingRequests));
        tcpListenerThread.IsBackground = true;
        tcpListenerThread.Start();
    }

    // Update is called once per frame
    void Update()
    {
        statusText.SetText(status);
        dataText.SetText(data);
    }

    /// <summary>   
    /// Runs in background TcpServerThread; Handles incoming TcpClient requests     
    /// </summary>  
    private void ListenForIncomingRequests()
    {
        try
        {
            // Create listener on raspi IP address port 9090.           
            tcpListener = new TcpListener(IPAddress.Parse("192.168.1.152"), 9090);
            tcpListener.Start();
            data = "Waiting...";
            status = "Server is listening";
            Byte[] bytes = new Byte[16];
            while (true)
            {
                status = "Waiting for client";
                Thread.Sleep(10);
                using (connectedTcpClient = tcpListener.AcceptTcpClient())
                {
                    status = "Client accepted";
                    //Get a stream object for reading
                    using (NetworkStream stream = connectedTcpClient.GetStream())
                    {
                        int length;
                        // Read incoming stream into byte arrary.                       
                        while ((length = stream.Read(bytes, 0, bytes.Length)) != 0)
                        {
                            clientMessage = System.Text.Encoding.ASCII.GetString(bytes, 0, length);
                            status = "Message received!";
                            data = clientMessage;
                            SendMessage(clientMessage);
                        }
                    }
                }
            }
        }
        catch (SocketException socketException)
        {
            status = "SocketException " + socketException.ToString();
        }
    }
    /// <summary>   
    /// Send message to client using socket connection.     
    /// </summary>  
    private void SendMessage(string message)
    {
        if (connectedTcpClient == null)
        {
            return;
        }

        try
        {
            // Get a stream object for writing.             
            NetworkStream stream = connectedTcpClient.GetStream();
            if (stream.CanWrite)
            {
                string serverMessage = message;
                // Convert string message to byte array.                 
                byte[] serverMessageAsByteArray = System.Text.Encoding.ASCII.GetBytes(serverMessage);
                // Write byte array to socketConnection stream.               
                stream.Write(serverMessageAsByteArray, 0, serverMessageAsByteArray.Length);
                status = "Server sent message - should be received by client";
            }
        }
        catch (SocketException socketException)
        {
            status = "SocketException " + socketException.ToString();
        }
    }
}

排查建议

  1. 修正Unity端监听IP:不要硬编码固定IP,改用IPAddress.Any监听所有可用网卡,避免模拟器IP和代码中IP不匹配的问题:
    tcpListener = new TcpListener(IPAddress.Any, 9090);
    
  2. 确认模拟器网络映射:HoloLens 2模拟器运行在Hyper-V虚拟机中,需确保宿主机和模拟器网络连通:
    • 在模拟器中打开命令提示符,执行ipconfig获取真实IP;
    • 在宿主机ping该IP,确认连通性;
    • 若ping不通,检查Hyper-V虚拟交换机设置,确保虚拟机和宿主机在同一网络段。
  3. 检查防火墙规则:
    • 宿主机防火墙需允许Unity应用和Python脚本通过9090端口通信;
    • 模拟器内的Windows防火墙需开放9090端口的TCP入站规则。
  4. 线程安全修正:后台线程修改status和data时需加锁,避免与主线程的Update函数产生冲突:
    private readonly object lockObj = new object();
    
    // 后台线程修改状态时
    lock(lockObj)
    {
        status = "Waiting for client";
    }
    
    // Update函数读取状态时
    lock(lockObj)
    {
        statusText.SetText(status);
        dataText.SetText(data);
    }
    
  5. 模拟器内调试:使用Visual Studio远程调试模拟器,查看Debug.Log输出,确认是否有未捕获的异常;或在模拟器内运行TCP测试工具(如NetCat),验证端口监听是否正常。
  6. 双向连通性测试:
    • 在模拟器中运行TCP服务器,用Python脚本连接,确认基础通信是否正常;
    • 在宿主机运行TCP服务器,让Unity应用作为客户端连接,排查是服务器端还是客户端逻辑问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:10:58