유니티 네트워크 (Unity Socket with Thread) feat. Marshal

Server
-----------------------------------------------

using UnityEngine;
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine.UI;
using System.Runtime.InteropServices;

public class StateObject
{
    public Socket workSocket = null;
    public const int BufferSize = 10240;
    public byte[] buffer = new byte[BufferSize];
    //public StringBuilder sb = new StringBuilder();
}

public struct PackData
{
    public int width;
    public int height;
    public int size;

    public void GetData(byte[] bytes, Type type)
    {
        IntPtr buff = Marshal.AllocHGlobal(bytes.Length);
        Marshal.Copy(bytes, 0, buff, bytes.Length);
        object ob = Marshal.PtrToStructure(buff, type);
        this = (PackData)ob;

        Marshal.FreeHGlobal(buff);
    }
}

public class SocketAsyncServer : MonoBehaviour {

    public ManualResetEvent allDone = new ManualResetEvent(false);

    Thread m_socketThread;
    StateObject m_stateObj = new StateObject();
    PackData m_packData = new PackData();

    void Start()
    {
        Application.runInBackground = true;
        startServer();
    }

    void startServer()
    {
        m_socketThread = new Thread(networkCode);
        m_socketThread.IsBackground = true;
        m_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;
    }


    void networkCode()
    {
        byte[] bytes = null;

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

        Socket listener = new Socket(ipArray[0].AddressFamily,
            SocketType.Stream, ProtocolType.Tcp);

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

            while (true)
            {
                allDone.Reset();

                Debug.Log("Waiting for a connection...");
                listener.BeginAccept(
                    new AsyncCallback(AcceptCallback), listener);

                allDone.WaitOne();
            }
 
        }
        catch (System.Exception e)
        {
            Debug.Log(e.ToString());
        }
    }

    public void AcceptCallback(IAsyncResult ar)
    {
        allDone.Set();

        Socket listener = (Socket)ar.AsyncState;
        Socket handler = listener.EndAccept(ar);

        m_stateObj.workSocket = handler;
        handler.BeginReceive(m_stateObj.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReadCallback), m_stateObj);
    }

    public void ReadCallback(IAsyncResult ar)
    {
        string content = string.Empty;
        Socket handler = m_stateObj.workSocket;
        int bytesRead = handler.EndReceive(ar);

        if(bytesRead > 0)
        {
            //Use m_stateObj.buffer, bytesRead



                                               
            // Loop Accept
            handler.BeginReceive(m_stateObj.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReadCallback), m_stateObj);

        }
    }

    //private void Send(Socket handler, string data)
    //{
    //    byte[] byteData = Encoding.ASCII.GetBytes(data);

    //    handler.BeginSend(byteData, 0, byteData.Length, 0,
    //        new AsyncCallback(SendCallback), handler);
    //}
 
    //private void SendCallback(IAsyncResult ar)
    //{
    //    try
    //    {
    //        Socket handler = (Socket)ar.AsyncState;

    //        int byteSent = handler.EndSend(ar);
    //        Debug.Log("Sent bytes to client" + byteSent);

    //        handler.Shutdown(SocketShutdown.Both);
    //        handler.Close();
    //    }
    //    catch (Exception e)
    //    {
    //        Debug.Log(e.ToString());
    //    }
    //}


    private void OnDisable()
    {
        if(null != m_stateObj.workSocket)
        {
            m_stateObj.workSocket.Shutdown(SocketShutdown.Both);
            m_stateObj.workSocket.Close();
        }     
    }
}




Client
-----------------------------------------------

using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Runtime.InteropServices;

public class StateObject
{
    public Socket workSocket = null;
    public const int BufferSize = 256;
    public byte[] buffer = new byte[BufferSize];
    public StringBuilder sb = new StringBuilder();
}

//[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct PackData
{
    public int width;
    public int height;
    public int size;

    //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
    //public byte[] data;

    public byte[] GetBytes()
    {
        int size = Marshal.SizeOf(this);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.StructureToPtr(this, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);

        return arr;
    }
}

public class SocketAsyncClient : MonoBehaviour {

    public RenderTexture texture;

    string ipAdress = "192.168.0.1";
    private const int port = 1755;

    private ManualResetEvent connectDone =
        new ManualResetEvent(false);
    private ManualResetEvent sendDone =
        new ManualResetEvent(false);
    private ManualResetEvent receiveDone =
        new ManualResetEvent(false);

    private string response = string.Empty;

    Thread m_socketThread;
    Socket client;


    void Start () {
        StartClient();
    }

    private void StartClient()
    {
        m_socketThread = new Thread(networkCode);
        m_socketThread.Start();
    }

    void networkCode()
    {
        try
        {
            IPAddress ipAddr = IPAddress.Parse(ipAdress);
            IPEndPoint ipendPoint = new IPEndPoint(ipAddr, port);

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

            // Connect to the remote endpoint.
            client.BeginConnect(ipendPoint,
                new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();

            //// Send test data to the remote device.
            //Send(client, "This is a test");
            //sendDone.WaitOne();

            ////// Receive the response from the remote device.
            ////Receive(client);
            ////receiveDone.WaitOne();

            //// Write the response to the console.
            ////Debug.Log("Response received : {0}");

            //// Release the socket.
            //client.Shutdown(SocketShutdown.Both);
            //client.Close();

        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }

    private void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket client = (Socket)ar.AsyncState;

            // Complete the connection.
            client.EndConnect(ar);

            //Debug.Log("Socket connected to {0}");

            // Signal that the connection has been made.
            connectDone.Set();
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }

    private void Receive(Socket client)
    {
        try
        {
            // Create the state object.
            StateObject state = new StateObject();
            state.workSocket = client;

            // Begin receiving the data from the remote device.
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveCallback), state);
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }

    private void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the state object and the client socket
            // from the asynchronous state object.
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;

            // Read data from the remote device.
            int bytesRead = client.EndReceive(ar);

            if (bytesRead > 0)
            {
                // There might be more data, so store the data received so far.
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

                // Get the rest of the data.
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                    new AsyncCallback(ReceiveCallback), state);
            }
            else
            {
                // All the data has arrived; put it in response.
                if (state.sb.Length > 1)
                {
                    response = state.sb.ToString();
                }
                // Signal that all bytes have been received.
                receiveDone.Set();
            }
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }

    private void Send(Socket client, string data)
    {
        // Convert the string data to byte data using ASCII encoding.
        byte[] byteData = Encoding.ASCII.GetBytes(data);

        // Begin sending the data to the remote device.
        client.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), client);
    }

    private void Send(Socket client, byte[] byteData)
    {
        // Convert the string data to byte data using ASCII encoding.
        //byte[] byteData = Encoding.ASCII.GetBytes(data);

        // Begin sending the data to the remote device.
        client.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), client);
    }

    private void SendCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.
            Socket client = (Socket)ar.AsyncState;

            // Complete sending the data to the remote device.
            int bytesSent = client.EndSend(ar);
            //Debug.Log("Sent {0} bytes to server.");

            // Signal that all bytes have been sent.
            sendDone.Set();
        }
        catch (Exception e)
        {
            Debug.Log(e.ToString());
        }
    }
}


댓글

이 블로그의 인기 게시물

유니티 텍스쳐 생성 (Unity Texture Create from bytes)

유니티 네트워크 (Unity NetworkManager Component)

유니티 네트워크 (Unity Socket)