Unity 中的简单套接字服务器 [英] Simple socket server in Unity

查看:24
本文介绍了Unity 中的简单套接字服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的 Unity 项目中使用 C# 插件.该插件应充当服务器,从客户端获取值,以便我能够使用这些值进行进一步处理.问题是服务器有无限循环.无限循环会导致 Unity 挂起.如何处理?

I want to use a C# plugin in my Unity project. That plugin should act as a server which will get values from a client so that I'd be able to use those values for further processing. The issue is that the server has infinite loop. And infinite loops cause Unity to hang. How to handle this?

我附上了服务器程序的代码片段.在我看来,有两点可能会导致问题.代码中注释的无限循环和程序挂起的点:

I'm attaching a code snippet of server program. In my opinion, there are 2 points which may be causing problem. The infinite loops and the point where program is suspended as commented in code:

void networkCode()
{
    // Data buffer for incoming data.
    byte[] bytes = new Byte[1024];

    // Establish the local endpoint for the socket.
    // Dns.GetHostName returns the name of the 
    // host running the application.
    IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
    IPAddress ipAddress = ipHostInfo.AddressList[0];
    IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 1755);

    // Create a TCP/IP socket.
    listener = new Socket(ipAddress.AddressFamily,
        SocketType.Stream, ProtocolType.Tcp);

    // Bind the socket to the local endpoint and 
    // listen for incoming connections.
    try
    {
        listener.Bind(localEndPoint);
        listener.Listen(10);

        // Start listening for connections.
        while (true)
        {
            // Program is suspended while waiting for an incoming connection.
            Debug.Log("HELLO");     //It works
            handler = listener.Accept();
            Debug.Log("HELLO");     //It doesn't work
            data = null;

            // An incoming connection needs to be processed.
            while (true)
            {
                bytes = new byte[1024];
                int bytesRec = handler.Receive(bytes);
                data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
                if (data.IndexOf("<EOF>") > -1)
                {
                    break;
                }

                System.Threading.Thread.Sleep(1);
            }   

            System.Threading.Thread.Sleep(1);
        }
    }
    catch (Exception e)
    {
        Debug.Log(e.ToString());
    }
}

在@Programmer 的帮助下,C# 插件已完成.但是 Unity 没有读取正确的值.我附上了 Unity 端代码:

After help from @Programmer, the C# plugin is complete. But Unity is not reading the correct values. I'm attaching the Unity side code:

using UnityEngine;
using System;

using SyncServerDLL;    //That's our library

public class receiver : MonoBehaviour {

    SynchronousSocketListener obj;   //That's object to call server methods

    // Use this for initialization
    void Start() {
        obj = new SynchronousSocketListener ();
        obj.startServer ();
    }

    // Update is called once per frame
    void Update() {
        Debug.Log (obj.data);
    }
}

我已经在 Visual Studio 中彻底测试了 SynchronousSocketListener 类.在那里取得了很好的结果.

I have tested SynchronousSocketListener class thoroughly in Visual Studio. It is giving good results there.

推荐答案

使用 线程 来做你的服务器监听和读写操作.您可以将套接字和其他网络流对象声明为公共对象,然后在线程函数中对其进行初始化.

Use Thread to do your server Listen and read and write actions. You can declare socket and other networkstream objects as public then initialize them in a thread function.

Unity 不适用于线程中的 while 循环,有时可能冻结,但您可以通过添加 System.Threading.Thread.Sleep(1); 在您的 while 循环中,您正在读取或等待数据从套接字到达.

Unity does not work well with while loops in Threads and may freeze sometimes, but you can fix that by adding System.Threading.Thread.Sleep(1); in your while loop where you are reading or waiting for data to arrive from socket.

确保在OnDisable() 函数中停止线程.不要不要从新的线程函数访问 Unity API.只需在那里执行套接字操作并将数据返回到公共变量.

Make sure to stop the Thread in OnDisable() function. Do NOT access Unity API from the new Thread function. Just do only the socket stuff there and return the data to a public variable.

System.Threading.Thread SocketThread;
volatile bool keepReading = false;

// Use this for initialization
void Start()
{
    Application.runInBackground = true;
    startServer();
}

void startServer()
{
    SocketThread = new System.Threading.Thread(networkCode);
    SocketThread.IsBackground = true;
    SocketThread.Start();
}



private string getIPAddress()
{
    IPHostEntry host;
    string localIP = "";
    host = Dns.GetHostEntry(Dns.GetHostName());
    foreach (IPAddress ip in host.AddressList)
    {
        if (ip.AddressFamily == AddressFamily.InterNetwork)
        {
            localIP = ip.ToString();
        }

    }
    return localIP;
}


Socket listener;
Socket handler;

void networkCode()
{
    string data;

    // Data buffer for incoming data.
    byte[] bytes = new Byte[1024];

    // host running the application.
    Debug.Log("Ip " + getIPAddress().ToString());
    IPAddress[] ipArray = Dns.GetHostAddresses(getIPAddress());
    IPEndPoint localEndPoint = new IPEndPoint(ipArray[0], 1755);

    // Create a TCP/IP socket.
    listener = new Socket(ipArray[0].AddressFamily,
        SocketType.Stream, ProtocolType.Tcp);

    // Bind the socket to the local endpoint and 
    // listen for incoming connections.

    try
    {
        listener.Bind(localEndPoint);
        listener.Listen(10);

        // Start listening for connections.
        while (true)
        {
            keepReading = true;

            // Program is suspended while waiting for an incoming connection.
            Debug.Log("Waiting for Connection");     //It works

            handler = listener.Accept();
            Debug.Log("Client Connected");     //It doesn't work
            data = null;

            // An incoming connection needs to be processed.
            while (keepReading)
            {
                bytes = new byte[1024];
                int bytesRec = handler.Receive(bytes);
                Debug.Log("Received from Server");

                if (bytesRec <= 0)
                {
                    keepReading = false;
                    handler.Disconnect(true);
                    break;
                }

                data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
                if (data.IndexOf("<EOF>") > -1)
                {
                    break;
                }

                System.Threading.Thread.Sleep(1);
            }

            System.Threading.Thread.Sleep(1);
        }
    }
    catch (Exception e)
    {
        Debug.Log(e.ToString());
    }
}

void stopServer()
{
    keepReading = false;

    //stop thread
    if (SocketThread != null)
    {
        SocketThread.Abort();
    }

    if (handler != null && handler.Connected)
    {
        handler.Disconnect(false);
        Debug.Log("Disconnected!");
    }
}

void OnDisable()
{
    stopServer();
}

这篇关于Unity 中的简单套接字服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆