HoloLens、Unity和PC的Socket通讯问题

视频演示: https://live.csdn.net/v/414881?spm=1001.2014.3001.5501
基于System.Net.Socket和System.Net.Http均是可以实现的
在与HoloLens通讯过程中需要关闭Microsoft Defender防火墙,以System.Net.Socket为例,不然会报错SocketExpection. Connection Timed Out

如果有帮助记得点个赞
在这里插入图片描述

HoloLens与PC进行Socket通讯最好不采用UTF-8编码,自己定义编码及解码方式,这也是Socket通讯的优势
在这里插入图片描述
下面程序中is_xx是bool,谁要是想用下面的代码的话可以将第一段放在一个Button下面,同时取private bool is_socket = false;
传输矩阵或者数字的话可以直接用我的,若有其他需求可以自己定义自己的编码方式。

//这是第一段需要放在button下的
 Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

 List<Socket> clientSocketsList = new List<Socket>();

 if (!is_socket)
 {
     is_socket = true;

     LogBox.AppendText("远程通讯中" + Environment.NewLine);
     socket_conn.IconColor = Color.Red;

     string IP = this.textBox1.Text;
     int port = Convert.ToInt32(this.textBox2.Text);

     IPAddress ip = IPAddress.Parse(IP);
     IPEndPoint endPoint = new IPEndPoint(ip, port);
     serverSocket.Bind(endPoint);

     serverSocket.Listen(10);// 开始监听
     LogBox.AppendText("服务器多线程已启动,正在监听HoloLens连接..." + Environment.NewLine);

     //client_Socket = serverSocket.Accept();

     new Thread(() =>
     {
         //client_Socket = serverSocket.Accept();// 等待客户端连接
         while (true)
         {
             // 检查是否有已连接的客户端
             if (serverSocket.Poll(0, SelectMode.SelectRead))
             {
                 // 有新的客户端连接请求
                 Socket newtempSocket = serverSocket.Accept();
                 clientSocketsList.Add(newtempSocket);

                 LogBox.Invoke((MethodInvoker)delegate
                 {
                     LogBox.AppendText("新接入一个设备:" + newtempSocket.RemoteEndPoint.ToString()+ Environment.NewLine);
                 });
                 Console.WriteLine("新接入一个设备:" + newtempSocket.RemoteEndPoint.ToString());
             }
             for (int i = 0; i < clientSocketsList.Count; i++)
             {
                 if (clientSocketsList[i].Poll(0, SelectMode.SelectRead))
                 {
                     LogBox.Invoke((MethodInvoker)delegate
                     {
                         LogBox.AppendText("断开入一个设备:" + clientSocketsList[i].RemoteEndPoint.ToString() + Environment.NewLine);
                     });
                     Console.WriteLine("断开入一个设备:" + clientSocketsList[i].RemoteEndPoint.ToString());
                     clientSocketsList[i].Shutdown(SocketShutdown.Both);
                     clientSocketsList[i].Close();
                     clientSocketsList.RemoveAt(i);
                     i--;
                 }
             }
             if (clientSocketsList.Count > 0)
             {
                 try
                 {
                     pose ndipose = new pose();
                     if (is_CAM_socket_model)
                     {
                         ndipose.m00 = global_varible.CAM_postureMat4x4.M11;
                         ndipose.m01 = global_varible.CAM_postureMat4x4.M12;
                         ndipose.m02 = global_varible.CAM_postureMat4x4.M13;
                         ndipose.m03 = global_varible.CAM_postureMat4x4.M14;

                         ndipose.m10 = global_varible.CAM_postureMat4x4.M21;
                         ndipose.m11 = global_varible.CAM_postureMat4x4.M22;
                         ndipose.m12 = global_varible.CAM_postureMat4x4.M23;
                         ndipose.m13 = global_varible.CAM_postureMat4x4.M24;

                         ndipose.m20 = global_varible.CAM_postureMat4x4.M31;
                         ndipose.m21 = global_varible.CAM_postureMat4x4.M32;
                         ndipose.m22 = global_varible.CAM_postureMat4x4.M33;
                         ndipose.m23 = global_varible.CAM_postureMat4x4.M34;

                         ndipose.m30 = global_varible.CAM_postureMat4x4.M41;
                         ndipose.m31 = global_varible.CAM_postureMat4x4.M42;
                         ndipose.m32 = global_varible.CAM_postureMat4x4.M43;
                         ndipose.m33 = global_varible.CAM_postureMat4x4.M44;
                     }
                     if (is_NDI_socket_model)//优先传输NDI,同时打开覆盖CAM数据
                     {
                         ndipose.m00 = global_varible.NDI_posture.M11;
                         ndipose.m01 = global_varible.NDI_posture.M12;
                         ndipose.m02 = global_varible.NDI_posture.M13;
                         ndipose.m03 = global_varible.NDI_posture.M14;

                         ndipose.m10 = global_varible.NDI_posture.M21;
                         ndipose.m11 = global_varible.NDI_posture.M22;
                         ndipose.m12 = global_varible.NDI_posture.M23;
                         ndipose.m13 = global_varible.NDI_posture.M24;

                         ndipose.m20 = global_varible.NDI_posture.M31;
                         ndipose.m21 = global_varible.NDI_posture.M32;
                         ndipose.m22 = global_varible.NDI_posture.M33;
                         ndipose.m23 = global_varible.NDI_posture.M34;

                         ndipose.m30 = global_varible.NDI_posture.M41;
                         ndipose.m31 = global_varible.NDI_posture.M42;
                         ndipose.m32 = global_varible.NDI_posture.M43;
                         ndipose.m33 = global_varible.NDI_posture.M44;
                     }
                     byte[] tempbytes = new byte[1024];

                     tempbytes = StructToByte(ndipose);

                     for (int i = 0; i < clientSocketsList.Count; i++)//send data for all client device
                         clientSocketsList[i].Send(tempbytes);

                     LogBox.Invoke((MethodInvoker)delegate
                     {
                         LogBox.AppendText("Send Message +1" + Environment.NewLine);
                     });

                 }
                 catch (Exception ex)
                 {
                     Console.WriteLine(ex.ToString());
                     this.Close();

                     for (int i = 0; i < clientSocketsList.Count; i++)//send data for all client device
                         clientSocketsList[i].Shutdown(SocketShutdown.Both);
                     for (int i = 0; i < clientSocketsList.Count; i++)//send data for all client device
                         clientSocketsList[i].Close();
                 }
             }
             else
             { 

             }
         }
     }).Start();
 }
 else
 {
     //server_Socket = serverSocket.Accept();

     LogBox.AppendText("已断开socket连接");

     is_socket = false;

     serverSocket.Close();

     //SocketConnect.Text = "";
     socket_conn.IconColor = Color.White;
     //SocketConnect.ImageAlign = ContentAlignment.MiddleCenter;

 }

同时复制下面程序到Button外:

 public static byte[] StructToByte(pose poseData)
 {
     int size = Marshal.SizeOf(typeof(pose));
     byte[] buffer = new byte[size];

     IntPtr ptr = Marshal.AllocHGlobal(size);
     Marshal.StructureToPtr(poseData, ptr, true);
     Marshal.Copy(ptr, buffer, 0, size);
     Marshal.FreeHGlobal(ptr);

     return buffer;
 }
  public struct pose
 {
     public float m00;
     public float m01;
     public float m02;
     public float m03;
     public float m10;
     public float m11;
     public float m12;
     public float m13;
     public float m20;
     public float m21;
     public float m22;
     public float m23;
     public float m30;
     public float m31;
     public float m32;
     public float m33;
 }

--------------------------------分界线
在HoloLens端解码方式,和上面没关系了,创建一个scoket.cs脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System;

public class scoket : MonoBehaviour
{
    [Header("Static")]
    public static scoket client; //脚本内的全局变量

    [Header("Network")]
    private bool activeConnection = true; //判断是否尝试连接的变量
    private Socket mClient;
    public string mIp = "192.168.3.11"; //连接 IP
    public int mPort = 8888; //连接端口
    [HideInInspector] public pose ReceivedPose = new pose();
    private IPEndPoint mServerIpEndPoint;

    private bool is_connect2_pc = false;
    private void Awake()
    {
        client = this;
    }

    public void Start()
    {
        if (activeConnection) //尝试连接
        {
            InitClient(); 
            is_connect2_pc = true;
        }
    }

    private void Update()
    {
        if (activeConnection) 
        {
            Receive(); 
            //
        }
    }

    public void OnApplicationQuit()
    {
        is_connect2_pc = false;

        CloseClient();
    }

    private void InitClient()
    {
        mServerIpEndPoint = new IPEndPoint(IPAddress.Parse(mIp), mPort);
        mClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        mClient.Connect(mServerIpEndPoint);
        Debug.Log(mClient.RemoteEndPoint.ToString());
    }

    private void Receive()
    {
        if (is_connect2_pc)
        {
            int receive = 0;
            //Debug.Log(mClient.Available);
            if (mClient.Available != 0)//client.Available属性返回内部缓冲区中已接收但尚未读取的数据的字节数。
            {
                byte[] packet = new byte[1024];

                try
                {
                    receive = mClient.Receive(packet);//packet为接收包
                }

                catch (Exception)
                {
                    return;
                }

                //mReceivePacket = ByteArrayToStruct<Packet>(packet); //存储数据包
                ReceivedPose = ByteArrayToArrayStruct<pose>(packet); //存储数据包

                Debug.Log("rows1:" + ReceivedPose.m00 + ";" + ReceivedPose.m01 + ";" + ReceivedPose.m02 + ";" + ReceivedPose.m03);
                Debug.Log("rows2:" + ReceivedPose.m10 + ";" + ReceivedPose.m11 + ";" + ReceivedPose.m12 + ";" + ReceivedPose.m13);
                Debug.Log("rows3:" + ReceivedPose.m20 + ";" + ReceivedPose.m21 + ";" + ReceivedPose.m22 + ";" + ReceivedPose.m23);
                Debug.Log("rows4:" + ReceivedPose.m30 + ";" + ReceivedPose.m31 + ";" + ReceivedPose.m32 + ";" + ReceivedPose.m33);
            }
            else
            {
                Debug.Log("Receive Nothing");
            }
        }
    }

    private void CloseClient()
    {
        if (mClient != null)
        {
            mClient.Close();
            mClient = null;
        }
    }

    private T ByteArrayToStruct<T>(byte[] buffer) where T : struct
    {
        int size = Marshal.SizeOf(typeof(T));
        if (size > buffer.Length)
        {
            throw new Exception();
        }

        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.Copy(buffer, 0, ptr, size);
        T obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
        Marshal.FreeHGlobal(ptr);
        return obj;
    }
    private T ByteArrayToArrayStruct<T>(byte[] buffer) where T : struct
    {
        int size = Marshal.SizeOf(typeof(T));
        if (size > buffer.Length)
        {
            throw new Exception();
        }

        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.Copy(buffer, 0, ptr, size);
        T obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
        Marshal.FreeHGlobal(ptr);
        return obj;
    }
}
public struct pose
{
    public float m00;
    public float m01;
    public float m02;
    public float m03;
    public float m10;
    public float m11;
    public float m12;
    public float m13;
    public float m20;
    public float m21;
    public float m22;
    public float m23;
    public float m30;
    public float m31;
    public float m32;
    public float m33;
}

如下图所示,在写这篇博客期间已测试半小时,可持续稳定实现数据传输
在这里插入图片描述
断开时可有消息提示
在这里插入图片描述

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Unity3D编写Socket通讯来控制机器人,您需要遵循以下步骤: 1. 创建Socket连接:创建一个Socket对象,并且连接到机器人的IP地址和端口号。 2. 发送数据:使用Socket对象的Send方法,将控制指令通过网络发送给机器人。 3. 接收数据:使用Socket对象的Receive方法,监听机器人发送的反馈信息。 4. 解析数据:将机器人反馈的信息进行解析,并且根据解析结果来判断控制是否成功。 下面是一个示例代码: ``` using UnityEngine; using System.Net; using System.Net.Sockets; public class SocketClient : MonoBehaviour { Socket client; void Start() { client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPAddress ipAddress = IPAddress.Parse("192.168.1.100"); IPEndPoint remoteEP = new IPEndPoint(ipAddress, 6000); client.Connect(remoteEP); SendData("move:forward=1"); byte[] buffer = new byte[1024]; int bytesRec = client.Receive(buffer); string reply = Encoding.ASCII.GetString(buffer, 0, bytesRec); if (reply == "ok") { Debug.Log("Control success!"); } else { Debug.LogError("Control failed!"); } } void OnDestroy() { client.Shutdown(SocketShutdown.Both); client.Close(); } void SendData(string data) { byte[] message = Encoding.ASCII.GetBytes(data); client.Send(message); } } ``` 这个示例代码中,我们创建了一个Socket对象,连接到了IP地址为192.168.1.100的机器人,端口号为6000。然后我们向机器人发送了一个控制指令,该指令是向前移动一步。接着我们监听了机器人的反馈信息,并且通过解析来判断控制是否成功。 请注意,这个示例代码只是一个简单的示例,您需要根据机器人的具体情况和通讯协议来编写相应的代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值