Windows 10, Unity 5.5.2 - note that this implicitly restricts .Net to version 3.5.
I have a C++ application that I'm trying to connect to a Unity application over the air. I wish to continually send byte arrays from C++ to Unity. The catch is that, for the device (Hololens, in my case) that I wish to deploy to, System.Net.Sockets is not available.
In C++ I instantiate a socket using the Winsock2.h header. I can use UDP or TCP, it doesn't matter to me for my application.
In Unity, I wish to use either Unity.Networking or UWP to establish the connection.
To use UWP, I've only seen examples that use the async keyword, which is a headache to use in Unity (and I'm honestly not sure if it's possible).
Meanwhile, Unity.Networking seems to use its own protocol, and I'm not sure how to interface it with my C++ application.
Can anyone provide a very simple, concise way of accomplishing this task in Unity?
EDIT: Using Threads is difficult on the Hololens as well, async tasks seem to be a difficult proposition as well.
We have build a C++ to Unity UDP client using Threads and https://github.com/nickgravelyn/UnityToolbag/tree/master/Dispatcher to make it 'Thread safe'.
According to https://forums.hololens.com/discussion/578/hololens-udp-server you could use Windows.Networking.Sockets
After much trial and error, I finally got it halfway working. If someone can fill in the blanks in this answer (see below), I will gladly change the accept to their answer.
In short, I did wind up just using UWP TCP sockets. The build is kind of a pain, and it does not work on the emulator. The switch to hardware instead of the emulator made things work.
The necessary TCP C# listener that bulids with UWP for Hololens:
#define uwp
//#define uwp_build
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Text;
using System;
using System.Threading;
using System.Linq;
#if uwp
#if !uwp_build
using Windows.Networking;
using Windows.Networking.Sockets;
using UnityEngine.Networking;
using Windows.Foundation;
#endif
#else
using System.Net;
using System.Net.Sockets;
#endif
public class Renderer : MonoBehavior {
byte[] bytes = new byte[8192];
bool ready = false;
const int localPort = 11000;
static bool clientConnected;
#if !uwp
TcpListener listener;
private Socket client = null;
#else
#if !uwp_build
StreamSocketListener socketListener;
StreamSocket socket;
#endif
#endif
#if !uwp_build
async
#endif
void Start()
{
clientConnected = false;
#if !uwp
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
listener = new TcpListener(localAddr, localPort);
listener.Start();
Debug.Log("Started!");
#else
#if !uwp_build
socketListener = new StreamSocketListener();
socketListener.ConnectionReceived += OnConnection;
await socketListener.BindServiceNameAsync("11000");
}
#endif
#endif
void Update()
{
#if !uwp
if (listener.Pending())
{
client = listener.AcceptSocket();
clientConnected = true;
}
#endif
// An incoming connection needs to be processed.
//don't do anything if the client isn't connected
if (clientConnected)
{
int bytesRec = 0;
#if !uwp
bytesRec = client.Receive(bytes);
#else
#if !uwp_build
Stream streamIn = socket.InputStream.AsStreamForRead();
bytesRec = streamIn.Read(bytes, 0, 8192);
Debug.Log(bytesRec);
#endif
#endif
byte[] relevant_bytes = bytes.Take(bytesRec).ToArray();
//do something with these relevant_bytes
}
#if uwp
#if !uwp_build
private async void OnConnection(
StreamSocketListener sender,
StreamSocketListenerConnectionReceivedEventArgs args)
{
String statusMsg = "Received connection on port: " + args.Socket.Information.LocalPort;
Debug.Log(statusMsg);
this.socket = args.Socket;
clientConnected = true;
}
#endif
#endif
}
I have to build from unity with uwp_build enabled, and then deploy to the Hololens with it disabled - I'm not sure why.
At any rate, this works pretty seamlessly on the device itself. It doesn't work on the emulator. With the emulator seemingly being deprecated when Creators 10 releases in a week or so, this may be a moot point - maybe it will work on the new simulator. Since I'm communicating from non-UWP to UWP, I don't think loopback should be an issue when running on a local machine - especially since the emulator has a different IP address than the host device. If anyone knows why this would work on the device but not on the emulator and if there's a more convenient build flag sequence, I would be very grateful to know.
There is a Transport Layer API for such tasks. This is code from its samples:
// Initializing the Transport Layer with no arguments (default settings)
NetworkTransport.Init();
// An example of initializing the Transport Layer with custom settings
GlobalConfig gConfig = new GlobalConfig();
gConfig.MaxPacketSize = 500;
NetworkTransport.Init(gConfig);
ConnectionConfig config = new ConnectionConfig();
// use QosType.Reliable if you need TCP
int myReiliableChannelId = config.AddChannel(QosType.Reliable);
// use QosType.Unreliable if you need UDP
int myUnreliableChannelId = config.AddChannel(QosType.Unreliable);
HostTopology topology = new HostTopology(config, 10);
// set listen port 8888
int hostId = NetworkTransport.AddHost(topology, 8888);
Function for data receiving:
void Update()
{
int recHostId;
int connectionId;
int channelId;
byte[] recBuffer = new byte[1024];
int bufferSize = 1024;
int dataSize;
byte error;
NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
switch (recData)
{
case NetworkEventType.Nothing: //1
break;
case NetworkEventType.ConnectEvent: //2
break;
case NetworkEventType.DataEvent: //3
break;
case NetworkEventType.DisconnectEvent: //4
break;
}
}
For C/C++ part use standard network sockets. For examples you may check Beginner's Socket Programming in C
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With