Hololens的应用需要与其他设备通信的时候,UDP是比较方便的一种方式,Unity3d 2017.3 C#开发的时候可以用Windows.Networking.Sockets.DatagramSocket 类来接收、发送UDP消息,简单快捷。

.net 的System.net.Socket对象应该也可以,但是只支持部分方法,一开始没走通所以我没继续测试下去。

开发的时候注意两个地方:

1、DatagramSocket.MessageReceived 事件不在主线程运行,所以在这个事件中不能操作UI的东西,比如给文本框赋值,否则报错。

2、Unity Build的时候Player Settings要勾选 PrivateNetworkClientServer,注意跟InternetClientServer不一样。因为我是在局域网测试,一开始只是勾选了InternetClientServer,结果无法接收消息。

---------------------------------------

下面是网上找的一个UDP收发消息的类:

using UnityEngine;
using System;
using System.IO;
using System.Text;
using System.Linq;
using HoloToolkit.Unity;
using System.Collections.Generic;
using UnityEngine.Events; #if !UNITY_EDITOR
using Windows.Networking.Sockets;
using Windows.Networking.Connectivity;
using Windows.Networking;
#endif [System.Serializable]
public class UDPMessageEvent : UnityEvent<string, string, byte[]>
{ } public class UDPCommunication : Singleton<UDPCommunication>
{
[Tooltip("port to listen for incoming data")]
public string internalPort = "12345"; [Tooltip("IP-Address for sending")]
public string externalIP = "192.168.17.110"; [Tooltip("Port for sending")]
public string externalPort = "12346"; [Tooltip("Send a message at Startup")]
public bool sendPingAtStart = true; [Tooltip("Conten of Ping")]
public string PingMessage = "hello"; [Tooltip("Function to invoke at incoming packet")]
public UDPMessageEvent udpEvent = null; private readonly Queue<Action> ExecuteOnMainThread = new Queue<Action>(); #if !UNITY_EDITOR //we've got a message (data[]) from (host) in case of not assigned an event
void UDPMessageReceived(string host, string port, byte[] data)
{
Debug.Log("GOT MESSAGE FROM: " + host + " on port " + port + " " + data.Length.ToString() + " bytes ");
} //Send an UDP-Packet
public async void SendUDPMessage(string HostIP, string HostPort, byte[] data)
{
await _SendUDPMessage(HostIP, HostPort, data);
} DatagramSocket socket; async void Start()
{
if (udpEvent == null)
{
udpEvent = new UDPMessageEvent();
udpEvent.AddListener(UDPMessageReceived);
} Debug.Log("Waiting for a connection..."); /**
*关键点一:创建使用UDP的网络通信对象:DatagramSocket,然后添加接收消息的事件MessageReceived
*/
socket = new DatagramSocket();
socket.MessageReceived += Socket_MessageReceived; HostName IP = null;
try
{
var icp = NetworkInformation.GetInternetConnectionProfile(); IP = Windows.Networking.Connectivity.NetworkInformation.GetHostNames()
.SingleOrDefault(
hn =>
hn.IPInformation?.NetworkAdapter != null && hn.IPInformation.NetworkAdapter.NetworkAdapterId
== icp.NetworkAdapter.NetworkAdapterId);
/**
* 关键点二:绑定IP和监听端口,IP如果传null好像不行。
*/
await socket.BindEndpointAsync(IP, internalPort);
}
catch (Exception e)
{
Debug.Log(e.ToString());
Debug.Log(SocketError.GetStatus(e.HResult).ToString());
return;
} if (sendPingAtStart)
SendUDPMessage(externalIP, externalPort, Encoding.UTF8.GetBytes(PingMessage)); } private async System.Threading.Tasks.Task _SendUDPMessage(string externalIP, string externalPort, byte[] data)
{
using (var stream = await socket.GetOutputStreamAsync(new Windows.Networking.HostName(externalIP), externalPort))
{
using (var writer = new Windows.Storage.Streams.DataWriter(stream))
{
writer.WriteBytes(data);
await writer.StoreAsync(); }
}
} #else
// to make Unity-Editor happy :-)
void Start()
{ } public void SendUDPMessage(string HostIP, string HostPort, byte[] data)
{ } #endif static MemoryStream ToMemoryStream(Stream input)
{
try
{ // Read and write in
byte[] block = new byte[0x1000]; // blocks of 4K.
MemoryStream ms = new MemoryStream();
while (true)
{
int bytesRead = input.Read(block, 0, block.Length);
if (bytesRead == 0) return ms;
ms.Write(block, 0, bytesRead);
}
}
finally { }
} // Update is called once per frame
void Update()
{
/**
* 关键点四:由主线程触发事件,避免外面调用的类可能出错。
*/
while (ExecuteOnMainThread.Count > 0)
{
ExecuteOnMainThread.Dequeue().Invoke(); }
} #if !UNITY_EDITOR
private void Socket_MessageReceived(Windows.Networking.Sockets.DatagramSocket sender,
Windows.Networking.Sockets.DatagramSocketMessageReceivedEventArgs args)
{
Debug.Log("GOT MESSAGE FROM: " + args.RemoteAddress.DisplayName);
//Read the message that was received from the UDP client.
Stream streamIn = args.GetDataStream().AsStreamForRead();
MemoryStream ms = ToMemoryStream(streamIn);
byte[] msgData = ms.ToArray(); /**
* 关键点三:接收到数据用事件发送出去,这里只是把触发事件的代码放到队列ExecuteOnMainThread中。
* 是因为接收函数是多线程的,跟Unity主线程不一样,自己开发的时候如果在这里给文本框赋值会报错!
*/
if (ExecuteOnMainThread.Count == 0)
{
ExecuteOnMainThread.Enqueue(() =>
{
Debug.Log("ENQEUED ");
if (udpEvent != null)
udpEvent.Invoke(args.RemoteAddress.DisplayName, internalPort, msgData);
});
}
} #endif
}

  

然后是Player Settings截图:

Hololens开发笔记:UDP接收数据的更多相关文章

  1. iOS开发- 蓝牙后台接收数据(BLE4.0)

    最近在做一个蓝牙相关的项目, 需要在应用进入后台, 或者手机属于锁屏状态的情况下, 仍然保持蓝牙连接, 并且能正常接收数据. 本来以后会很麻烦, 但是学习了下..发现就2步而已.简单的不能再简单了. ...

  2. Hololens开发笔记之连接PC实现资源共享

    官网原文介绍:https://developer.microsoft.com/en-us/windows/holographic/using_the_windows_device_portal Hol ...

  3. Hololens开发笔记之使用Unity开发一个简单的应用

    一.Hololens概述 Hololens有以下特性 1.空间映射借助微软特殊定制的全息处理单元(HPU),HoloLens 实现了对周边环境的快速扫描和空间匹配.这保证了 HoloLens能够准确地 ...

  4. Hololens开发笔记之Gesture手势识别(手势检测反馈)

    本文实现当使用者手出现在Hololens视野范围内时,跟踪手并给出反馈的效果. 1.在Manager上添加HandsManager脚本组件,用于追踪识别手 HandsManager.cs如下(直接使用 ...

  5. HoloLens开发笔记之Gesture input手势输入

    手势是HoloLens三个首要输入形式之一.一旦你使用凝视定位了一个全息图像,手势允许你与它交互.手势输入允许你使用手或者点击器原生地与全息图像交互. 手势之外,你也可以在应用中使用语音输入来交互. ...

  6. Hololens开发笔记之Gesture手势识别(单击,双击)

    本文使用手势识别实现识别单击及双击手势的功能,当单击Cube时改变颜色为蓝色,当双击Cube时改变颜色为绿色. 手势识别是HoloLens交互的重要输入方法之一.HoloLens提供了底层API和高层 ...

  7. Hololens开发笔记之Gesture手势识别(基本介绍)

    手势识别是HoloLens交互的重要输入方法之一.HoloLens提供了底层API和高层API,可以满足不同的手势定制需求.底层API能够获取手的位置和速度信息,高层API则借助手势识别器来识别预设的 ...

  8. Hololens开发笔记之Gaze凝视射线

    凝视是HoloLens首要输入方式,形式功能类似于桌面系统的光标,用于选择操作全息对象.然而在Unity中并没有明确的Gaze API或者组件. 概念上来说,Gaze是通过用户头部两眼之间发出一条向前 ...

  9. ThinkPHP开发笔记-前后端数据交互

    此处就是 Controller 和 View 相互传数据. 1.Controller 向 View 的页面传数据.在控制器中把变量传递给模板,使用 assign 方法对模板变量赋值.例如: 在Cont ...

随机推荐

  1. C#-WebForm-★ASP.NET中的母版页★

    何为母版页,顾名思义母版就是模版,就像在PPT里面的板式或主题一样,大框架已经有了,我们的任务就是向里面添加具体的内容.这样我们制作的所有幻灯片的外观大体都是一样的. 在ASP.NET中母版页有两种作 ...

  2. 阿里云服务器18个数据中心测试IP地址以及测试方法

    我们用户在选择阿里云服务器的时候是不是感觉阿里云的数据中心太多太多,确实阿里云服务器机房是有很多,国外国外机房大约有18个,甚至更多,因为还在不断的增加机房.对于商家而言增加不同的机房可以满足不同的项 ...

  3. [ZJOI2019]Minimax搜索

    先求出根节点的权值\(w\).根据套路,我们对于每个\(k\),计算\(w(s)\leq k\)的方案数,差分得到答案.为了方便,接下来考虑计算概率而不是方案数. 可以发现,对于一个给定的有解的子集, ...

  4. 开源项目-Aiguille

        项目地址: https://github.com/wwkai555/Aiguille 这个项目主要使用Android L新特性 - 最新的widget以及一些值得推荐和使用的开源库比如butt ...

  5. (转)MySQL出现同步延迟有哪些原因?如何解决?

    http://oldboy.blog.51cto.com/2561410/1682147----MySQL出现同步延迟有哪些原因?如何解决? 原文:http://www.zjian.me/mysql/ ...

  6. JavaScript设计模式-21.命令模式

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. Manjaro安装笔记

    安装后就可以先配置国内的软件源.使用以下命令: #排列源 sudo pacman-mirrors -g https://www.jianshu.com/p/f2c9ee00698c https://w ...

  8. CC2530zigbee技术-简介协议栈

    前言 说实话,我喜欢自己的原创,虽然我写得可能简单了,但我觉得自己在写博客的路途上,一点一点地积累知识,我也借鉴别人的东西,特别是在写这篇文章时所使用的是markdownpad2写的,原来我根本就不知 ...

  9. SQL基本操作(工作中够用了)

      以下文章内容都是我自己从平时学习SQL语言时整理而来,写这篇文章是希望我或大家在使用能更方便的查询. 如果有不完整或不正确的地方请大家指出~谢谢大家 基本SQL操作 创建数据库 CREATE DA ...

  10. shell脚本分析apache日志状态码

    一.首先将apache日志按天切割 vi /etc/httpd/conf/httpd.conf        ErrorLog "|rotatelogs /var/log/httpd/%Y% ...