hololens 2 和计算机上的统一应用程序之间的 TCP 连接只能工作一次

Posted

技术标签:

【中文标题】hololens 2 和计算机上的统一应用程序之间的 TCP 连接只能工作一次【英文标题】:TCP connection between hololens 2 and a unity app on computer only works once 【发布时间】:2021-12-02 12:47:54 【问题描述】:

我尝试在 hololens 2 和 PC 上的统一应用程序之间建立 TCP 连接。现在它可以工作一次,但是连接失败。我真的不知道为什么。

Hololens 是服务器,PC 上的 Unity 应用程序是客户端。失败时,统一应用程序中的消息是“SocketException:现有连接被远程主机强制关闭”。我也尝试在 hololens 2 中捕获信息。它显示“已报告 ID 为 20000000068 的设备断开连接,但没有连接具有该 ID 的设备。

我的服务器代码:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

#if !UNITY_EDITOR
    using Windows.Networking;
    using Windows.Networking.Sockets;
    using Windows.Storage.Streams;
#endif

//Able to act as a reciever 
public class UniversalSampleTutorial : MonoBehaviour

    public String _input = "Waiting";

#if !UNITY_EDITOR
        StreamSocket socket;
        StreamSocketListener listener;
        String port;
        String message;
#endif

    // Use this for initialization
    void Start()
    
#if !UNITY_EDITOR
        listener = new StreamSocketListener();
        port = "9090";
        listener.ConnectionReceived += Listener_ConnectionReceived; // This means one connection build, whenever event will be triggered 
        listener.Control.KeepAlive = true; // control is like setting for streamsocket object, keep alive means constantly sending data, when no data, can send keep alive packet

        Listener_Start();
#endif
    

#if !UNITY_EDITOR
    private async void Listener_Start()
    
        Debug.Log("Listener started");
        try
        
            await listener.BindServiceNameAsync(port); // start to listening to a port
        
        catch (Exception e)
        
            Debug.Log("Error: " + e.Message);
        

        Debug.Log("Listening");
    

    private async void Listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
    
        Debug.Log("Connection received");

        try
        
            while (true) 

                    using (var dw = new DataWriter(args.Socket.OutputStream)) // args is a connection, that for the connection, we have sockets, and then you can write, use once
                    
                        dw.WriteString("Hello There");
                        await dw.StoreAsync();  // buffer data to stream
                        await dw.FlushAsync();
                        dw.DetachStream();
                      

                    using (var dr = new DataReader(args.Socket.InputStream))
                    
                        dr.InputStreamOptions = InputStreamOptions.Partial;
                        await dr.LoadAsync(12);
                        var input = dr.ReadString(12);
                        Debug.Log("received: " + input);
                        _input = input;
                    
            
        
        catch (Exception e)
        
            Debug.Log("disconnected!!!!!!!! " + e);
        

    

#endif

    void Update()
    
        this.GetComponent<TextMeshProUGUI>().text = _input;
    
 

我的客户代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
public class UnityClient : MonoBehaviour

    public string IP;
    public int port;
    public string GoHololens;
    private TcpClient client;
    private Thread clientReceiveThread;
    private void Start()
    
        ConnectToTcpServer();
    

    private void Update()
    
        if (Input.GetKeyDown(KeyCode.Space))
        
            SendMessage();
        
    



    private void ConnectToTcpServer()
    
        try
        
            clientReceiveThread = new Thread(new ThreadStart(ListenForData));
            clientReceiveThread.IsBackground = true; // set this thread is background thread or not
            clientReceiveThread.Start();
        
        catch (Exception _ex)
        
            Debug.Log("Faild to connect:" + _ex);
        
    

    private void ListenForData()
    
        try
        
            client = new TcpClient(IP, port);
            Byte[] bytes = new Byte[1024];
            while (true)
            
                // get stream object for reading
                using(NetworkStream stream = client.GetStream())
                
                    int length;
                    while((length=stream.Read(bytes, 0, bytes.Length)) != 0)
                    
                        var incomingData = new byte[length];
                        Array.Copy(bytes, 0, incomingData, 0, length);

                        string serverMessage = Encoding.ASCII.GetString(incomingData);
                        Debug.Log("server Message received as:" + serverMessage);
                    
                
            
        
        catch (SocketException socketExcep)
        
            Debug.Log("socket exception:" + socketExcep);
        

    

    private void SendMessage()
    
        if(client == null)
        
            Debug.Log("No tcp client exist");
            return;
        

        try
        
            NetworkStream stream = client.GetStream();
            if (stream.CanWrite)
            
                string clientMessage = GoHololens;
                byte[] clientMessageAsByteArray = Encoding.ASCII.GetBytes(clientMessage);

                stream.Write(clientMessageAsByteArray, 0, clientMessageAsByteArray.Length);
                Debug.Log("client send message");
            
        
        catch (SocketException socketExcep)
        
            Debug.Log("Socket exception:" + socketExcep);
        

    

【问题讨论】:

我们在设备上使用您的代码进行了测试并重现了您的问题。我们注意到崩溃发生在 Windows.Storage.Streams.DataReader.LoadAsync 方法中。接下来我们将使用固定缓冲区进行测试。 【参考方案1】:

我们已经验证了以下 C# 统一代码,没有将流包装器附加到其中的套接字流。

while (true) 
byte[] outdata = new byte[256];

//ABCDE
outdata[0] = 65;
outdata[1] = 66;
outdata[2] = 67;
outdata[3] = 68;
outdata[4] = 69;

var outbuffer = outdata.AsBuffer();
await args.Socket.OutputStream.WriteAsync(outbuffer);


byte[] data = new byte[256];
IBuffer buffer = data.AsBuffer();
uint bytesRead =12;


await args.Socket.InputStream.ReadAsync(buffer, bytesRead, Windows.Storage.Streams.InputStreamOptions.None);
var input = System.Text.Encoding.UTF8.GetString(buffer.ToArray());

Debug.Log("received: " + input);
_input = input;

【讨论】:

以上是关于hololens 2 和计算机上的统一应用程序之间的 TCP 连接只能工作一次的主要内容,如果未能解决你的问题,请参考以下文章

Hololens 2 和 Microsoft.MixedReality.QR 缺少方法异常

统一的 Git(和 Hololens)

是否可以访问 hololens 2 上的瞳孔直径等眼动追踪数据?

在 Unity 开发中使用 FileOpenPicker 应用程序合约 Hololens 2

Hololens 2 的光线投射问题

如何将HoloLens 2仿真器与本地UDP发送器连接