ChaosEmperor93
ChaosEmperor93

Reputation: 117

How to connect to Unity game server socket from UWP app via sockets?

I would like to send some heart rate values I receive from a Microsoft Band from a UWP app to Unity. I have currently a working Tcp Server in Unity but I could not seem to use System.Net.Sockets in UWP. Anyone knows how to make a tcp client on the UWP app and send the data to Unity?

My server code is as follows:

using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;

public class Server {

public static TcpListener listener;
public static Socket soc;
public static NetworkStream s;

public void StartService () {
    listener = new TcpListener (15579);
    listener.Start ();
    for(int i = 0;i < 1;i++){
        Thread t = new Thread(new ThreadStart(Service));
        t.Start();
    }       
}

void Service () {
    while (true) 
    {
        soc = listener.AcceptSocket ();
        s = new NetworkStream (soc);
        StreamReader sr = new StreamReader (s);
        StreamWriter sw = new StreamWriter (s);
        sw.AutoFlush = true;
        while(true)
        {
            string heartrate = sr.ReadLine ();
            if(heartrate != null)
            {
                HeartRateController.CurrentHeartRate = int.Parse(heartrate);
                Debug.Log(HeartRateController.CurrentHeartRate);
            }
            else if (heartrate == null)
            {
                break;
            }
        }
        s.Close();
    }
}

void OnApplicationQuit()
{
    Debug.Log ("END");
    listener.Stop ();
    s.Close();
    soc.Close();
}   
}

My UWP code is as follows:

    public IBandInfo[] pairedBands;
    public IBandClient bandClient;
    public IBandHeartRateReading heartreading;

    public MainPage()
    {
        this.InitializeComponent();
        ConnectWithBand();
    }

    public async void ConnectWithBand()
    {
        pairedBands = await BandClientManager.Instance.GetBandsAsync();

        try
        {
            if (pairedBands.Length > 0)
            {
                bandClient = await BandClientManager.Instance.ConnectAsync(pairedBands[0]);
            }
            else
            {
                return;
            }
        }
        catch (BandException ex)
        {
            textBlock.Text = ex.Message;
        }

        GetHeartRate();
    }

    public async void GetHeartRate()
    {
        IEnumerable<TimeSpan> supportedHeartBeatReportingIntervals = bandClient.SensorManager.HeartRate.SupportedReportingIntervals;
        bandClient.SensorManager.HeartRate.ReportingInterval = supportedHeartBeatReportingIntervals.First<TimeSpan>();

        bandClient.SensorManager.HeartRate.ReadingChanged += this.OnHeartRateChanged;

        try
        {
            await bandClient.SensorManager.HeartRate.StartReadingsAsync();
        }
        catch (BandException ex)
        {
            throw ex;
        }

        Window.Current.Closed += async (ss, ee) =>
        {
            try
            {
                await bandClient.SensorManager.HeartRate.StopReadingsAsync();
            }
            catch (BandException ex)
            {
                // handle a Band connection exception
                throw ex;
            }
        };
    }

    private async void OnHeartRateChanged(object sender, BandSensorReadingEventArgs<IBandHeartRateReading> e)
    {
        var hR = e.SensorReading.HeartRate;
        await textBlock.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () =>
        {
            textBlock.Text = hR.ToString();
        });
    }

Upvotes: 2

Views: 4371

Answers (1)

Programmer
Programmer

Reputation: 125245

After doing some research, UWP does not have the System.Net.Sockets; namespace. Even if you manage to add it there, it won't run after compiling. The new API is called StreamSocket socket. I found a full client example from here and modified it a little bit. Just call the connect function, send and read functions.

Important thing to understand is that you can't run this test on the-same PC. Your Unity server and UWP App MUST be running on different computers. Microsoft does not allow App to connect to another app on the-same computer when using UWP.

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;

namespace MyUniversalApp.Helpers
{
    public class SocketClient
    {
        StreamSocket socket;
        public async Task connect(string host, string port)
        {
            HostName hostName;

            using (socket = new StreamSocket())
            {
                hostName = new HostName(host);

                // Set NoDelay to false so that the Nagle algorithm is not disabled
                socket.Control.NoDelay = false;

                try
                {
                    // Connect to the server
                    await socket.ConnectAsync(hostName, port);
                }
                catch (Exception exception)
                {
                    switch (SocketError.GetStatus(exception.HResult))
                    {
                        case SocketErrorStatus.HostNotFound:
                            // Handle HostNotFound Error
                            throw;
                        default:
                            // If this is an unknown status it means that the error is fatal and retry will likely fail.
                            throw;
                    }
                }
            }
        }

        public async Task send(string message)
        {
            DataWriter writer;

            // Create the data writer object backed by the in-memory stream. 
            using (writer = new DataWriter(socket.OutputStream))
            {
                // Set the Unicode character encoding for the output stream
                writer.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
                // Specify the byte order of a stream.
                writer.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;

                // Gets the size of UTF-8 string.
                writer.MeasureString(message);
                // Write a string value to the output stream.
                writer.WriteString(message);

                // Send the contents of the writer to the backing stream.
                try
                {
                    await writer.StoreAsync();
                }
                catch (Exception exception)
                {
                    switch (SocketError.GetStatus(exception.HResult))
                    {
                        case SocketErrorStatus.HostNotFound:
                            // Handle HostNotFound Error
                            throw;
                        default:
                            // If this is an unknown status it means that the error is fatal and retry will likely fail.
                            throw;
                    }
                }

                await writer.FlushAsync();
                // In order to prolong the lifetime of the stream, detach it from the DataWriter
                writer.DetachStream();
            }
        }

        public async Task<String> read() 
        {
            DataReader reader;
            StringBuilder strBuilder;

            using (reader = new DataReader(socket.InputStream))
            {
                strBuilder = new StringBuilder();

                // Set the DataReader to only wait for available data (so that we don't have to know the data size)
                reader.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.Partial;
                // The encoding and byte order need to match the settings of the writer we previously used.
                reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
                reader.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;

                // Send the contents of the writer to the backing stream. 
                // Get the size of the buffer that has not been read.
                await reader.LoadAsync(256);

                // Keep reading until we consume the complete stream.
                while (reader.UnconsumedBufferLength > 0)
                {
                    strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));
                    await reader.LoadAsync(256);
                }

                reader.DetachStream();
                return strBuilder.ToString();
            }
        }
    }
}

Upvotes: 2

Related Questions