Hololens开发笔记:UDP接收数据
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接收数据的更多相关文章
- iOS开发- 蓝牙后台接收数据(BLE4.0)
最近在做一个蓝牙相关的项目, 需要在应用进入后台, 或者手机属于锁屏状态的情况下, 仍然保持蓝牙连接, 并且能正常接收数据. 本来以后会很麻烦, 但是学习了下..发现就2步而已.简单的不能再简单了. ...
- Hololens开发笔记之连接PC实现资源共享
官网原文介绍:https://developer.microsoft.com/en-us/windows/holographic/using_the_windows_device_portal Hol ...
- Hololens开发笔记之使用Unity开发一个简单的应用
一.Hololens概述 Hololens有以下特性 1.空间映射借助微软特殊定制的全息处理单元(HPU),HoloLens 实现了对周边环境的快速扫描和空间匹配.这保证了 HoloLens能够准确地 ...
- Hololens开发笔记之Gesture手势识别(手势检测反馈)
本文实现当使用者手出现在Hololens视野范围内时,跟踪手并给出反馈的效果. 1.在Manager上添加HandsManager脚本组件,用于追踪识别手 HandsManager.cs如下(直接使用 ...
- HoloLens开发笔记之Gesture input手势输入
手势是HoloLens三个首要输入形式之一.一旦你使用凝视定位了一个全息图像,手势允许你与它交互.手势输入允许你使用手或者点击器原生地与全息图像交互. 手势之外,你也可以在应用中使用语音输入来交互. ...
- Hololens开发笔记之Gesture手势识别(单击,双击)
本文使用手势识别实现识别单击及双击手势的功能,当单击Cube时改变颜色为蓝色,当双击Cube时改变颜色为绿色. 手势识别是HoloLens交互的重要输入方法之一.HoloLens提供了底层API和高层 ...
- Hololens开发笔记之Gesture手势识别(基本介绍)
手势识别是HoloLens交互的重要输入方法之一.HoloLens提供了底层API和高层API,可以满足不同的手势定制需求.底层API能够获取手的位置和速度信息,高层API则借助手势识别器来识别预设的 ...
- Hololens开发笔记之Gaze凝视射线
凝视是HoloLens首要输入方式,形式功能类似于桌面系统的光标,用于选择操作全息对象.然而在Unity中并没有明确的Gaze API或者组件. 概念上来说,Gaze是通过用户头部两眼之间发出一条向前 ...
- ThinkPHP开发笔记-前后端数据交互
此处就是 Controller 和 View 相互传数据. 1.Controller 向 View 的页面传数据.在控制器中把变量传递给模板,使用 assign 方法对模板变量赋值.例如: 在Cont ...
随机推荐
- C#生成验证码类
using System;using System.Collections.Generic;using System.Drawing;using System.Drawing.Drawing2D;us ...
- SpringDataRedis java.net.UnknownHostException: 127.0.0.1 错误
找了半天发现原来配置文件中多了一个空格; idea中properties文件的127.0.0.1后面出现了一个空格,编辑器将其变深黄色了
- 配置不同站点不同版本PHP
Apache 配置 1.常规手动部署apache方法(不会apache配置的请先移步看下Apache基本手工配置方法),解压fcgid,取其mod_fcgid.so至modules目录 2.打开htt ...
- MarkDown添加图片的三种方式
插图最基础的格式就是:  Alt text:图片的Alt标签,用来描述图片的关键词,可以不写.最初的本意是当图片 ...
- 【GIS新探索】算法实现在不规则区域内均匀分布点
1 概要 在不规则区域内均匀分布点,这个需求初看可能不好理解.如果设想一下需求场景就比较简单了. 场景1:在某个地区范围内,例如A市区有100W人口,需要将这100W人口在地图上面相对均匀的标识出来. ...
- window7 下安卓开发环境搭建
最新Win7下配置搭建安卓开发环境 注意:因为墙的原因 google的更新服务器需要改 hosts 你懂的.. 74.125.237.1 dl-ssl.google.com 不行就VPN ...
- struts2上传单个文件
项目目录: struts.xml配置: <constant name="struts.enable.DynamicMethodInvocation" value=" ...
- 利用IDEA创建Web Service服务端和客户端的详细过程
创建服务端 一.file–>new–>project 二.点击next后输入服务端名,点击finish,生成目录如下 三.在 HelloWorld.Java 文件中右击,选 WebServ ...
- css中字体单位px,pt,em,百分比之间的区别和用法
px 即像素,一般国内网站使用较多,默认大小是16px; pt 印刷行业常用单位 em 相对单位,相对父元素属性的单位 ,一般用于移动端布局 rem 结合相对定位和绝对定位的优势,相对根元素htm ...
- 低版本的linux系统装samba服务器
这里所用系统fedora14,安装samba服务器.我是壮壮熊. 由于工作原因,需要在feaord14上装samba服务器. 问题描述:用yum -y install samba安装samba后,需要 ...