【问题标题】:How to connect to Unity game server socket from UWP app via sockets?如何通过套接字从 UWP 应用程序连接到 Unity 游戏服务器套接字?
【发布时间】:2016-09-15 13:04:08
【问题描述】:

我想将我从 Microsoft Band 收到的一些心率值从 UWP 应用发送到 Unity。我目前在 Unity 中有一个工作的 Tcp 服务器,但我似乎无法在 UWP 中使用 System.Net.Sockets。有谁知道如何在 UWP 应用上制作 tcp 客户端并将数据发送到 Unity?

我的服务器代码如下:

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();
}   
}

我的UWP代码如下:

    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();
        });
    }

【问题讨论】:

  • 我有几个问题要问你。既然您决定使用TcpListner 而不是我发布的那个 Unity 服务器代码,是什么让您认为您编写的服务器代码有效?您在编写客户端代码之前是否对其进行了测试?我认为在没有测试服务器的情况下在客户端上工作会浪费时间。如果您不知道如何测试服务器,请告诉我。
  • @Programmer,我将同一台服务器用于另一个项目,该服务器与一个客户端连接,该客户端从通用 BLE 心率监视器获取心率值。它完美无缺。这是我一年前在 Stakeoverflow 上发布的代码:stackoverflow.com/questions/30161845/…
  • 好吧好吧。我想我以前回答过类似的问题。 stackoverflow.com/a/35890916/3785314我只是没有提供此人的代码。现在您需要让TcpClient 在您的 UWP 程序中工作吗?我以前从未使用过 UWP。 System.Net.Sockets; 命名空间在其中吗?
  • @Programmer,它是但它不包括 TcpClient。它似乎只使用套接字。我会在那里看看你的答案,然后告诉你。如果需要,我非常愿意使用与 TCP 不同的方法,只要它有效,哈哈
  • 等一下。不要费心去看那里。你所做的正是他所做的。如果找到答案。

标签: c# sockets unity3d uwp visual-studio-2015


【解决方案1】:

经过一些研究,UWP 确实没有拥有System.Net.Sockets; 命名空间。即使您设法将其添加到那里,它也不会在编译后运行。新的 API 称为 StreamSocket 套接字。我从here 中找到了一个完整的客户端示例,并对其进行了一些修改。只需调用连接函数、发送和读取函数即可。

需要了解的重要一点是,您不能在同一台 PC 上运行此测试。您的 Unity 服务器和 UWP 应用程序必须在不同的计算机上运行。 Microsoft 确实不允许在使用 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();
            }
        }
    }
}

【讨论】:

  • 哦,废话。我知道这太好了,不可能是真的。不幸的是,这不是我的选择。我需要它是本地的。我将在一周左右后展示我的游戏,但我不能保证可以上网。
  • @ChaosEmperor93 这是本地的。您必须连接到相同的路由器/network.wifi。你不明白吗?不。不需要互联网。只要确保它们都连接到相同的网络。如果你没有,你可以买一个简单的路由器。
  • 对不起,我在阅读您上面的评论之前发布了评论。问题是可能会有延迟,因为我的游戏具有多人游戏功能。在多人游戏中有一个选项仍然使用心率监测。对于未来,这不符合我的要求
  • @ChaosEmperor93 我需要它是本地的更正。那么可能会有延迟,因为我的游戏具有多人游戏功能。真的吗?简单的心率监测器应用程序滞后。要么你不知道 Tcp 和本地网络是什么,要么你只是不想用 TCP 来完成。我链接的答案提到了许多其他方法来做到这一点,但这个解决方案适用于 OP。无论如何,你运气不好。 Microsoft 未能为他们的设备制作 C++ API,因此您要么没有工作项目,要么没有工作项目。祝你好运!
  • 另外,后来我为消费者发布游戏时,需要两台机器来工作心率监测功能并不是一个令人愉快的解决方案。非常感谢您的帮助,但不幸的是,这不是一个选择。
猜你喜欢
  • 2021-12-15
  • 2021-06-24
  • 2019-07-10
  • 1970-01-01
  • 1970-01-01
  • 2019-12-10
  • 2016-08-15
  • 2012-02-29
  • 1970-01-01
相关资源
最近更新 更多