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. linux 编译PHP memcache扩展

    在Linux下编译memcache:memcache官网:http://memcached.org/前期准备:如果是虚拟机 保证虚拟机 联网安装依赖包yum -y install gcc make l ...

  2. 洛谷 P4774 / loj 2721 [NOI2018] 屠龙勇士 题解【同余】【exgcd】【CRT】

    推导过程存在漏洞+exCRT板子没打熟于是期望得分÷实际得分=∞? 题目描述 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照编号 \(1\sim n​\) 顺序杀掉 \(n​\ ...

  3. Pycharm 报错 AttributeError: module 'pip' has no attribute 'main'

    1.打开文件packaging_tool.py: D:\Program files\pycharm\PyCharm 2016.3.2\helpers\packaging_tool.py 2.添加导入: ...

  4. [iOS]使用Windows Azure來做iOS的推播通知 (转帖)

    這一篇我們用Windows Azure 的Mobile Service 來實作iOS的推播通知,底下我們分成三個階段來探討如何實作推播通知的服務: 第一階段: 開啓你的Windows Aure服務   ...

  5. 爬虫URL去重

    这个要看你想抓取的网页数量是哪种规模的.如果是千万以下用hash表, set, 布隆过滤器基本可以解决,如果是海量的......嗯我也没做过海量的,不过hash表之类的就别想了,内存根本不够,分割线下 ...

  6. 在eclipse中启动Tomcat报端口被占用的错误

    安装配置好Tomcat之后,在浏览器中输入localhost,能正取打开页面.然后在eclipse中建立项目,创建Servlet之后,启动Tomcat,报端口被占用的错误.如图: 原因:原来已经启动了 ...

  7. Cloudera Manager安装之Cloudera Manager安装前准备(CentOS6.5)(一)

    Cloudera Manager安装前准备 (一)机器准备 192.168.80.148   clouderamanager01 (部署ClouderaManager-server和Mirror se ...

  8. .net core 多平台部署

    首先下载地址 https://dotnet.microsoft.com/download 下载.net core 和  .net core runtime  然后安装他们 控制台运行项目: 找到你的工 ...

  9. PHP之mb_strstr使用

    mb_strstr (PHP 5 >= 5.2.0, PHP 7) mb_strstr - Finds first occurrence of a string within another 查 ...

  10. C 标准库 - ctype.h

    C 标准库 - ctype.h This header declares a set of functions to classify and transform individual charact ...