목차

    Unity3D 프로세스와 윈도우 폼 간의 통신 수행시 Tcp 서버에서 여러 클라이언트(유니티 프로세스)를 받을 수 있도록 하는 소스.
     

    Packet.cs

    using System;
     
    namespace Unity.Network
    {
        public enum PacketType
        {
            None, Connect, Reconnect, Disconnect, Chat,
        }
     
        [Serializable]
        public class Packet
        {
            public PacketType Type;
        }
     
        [Serializable]
        public class Connect : Packet
        {
            public string UserName;
        }
     
        [Serializable]
        public class ChatMessage : Packet
        {
            public string Message;
        }
    }

    PacketBinder.cs

    using System;

    using System.Reflection;

    using System.Runtime.Serialization;

     

    namespace Unity.Network

    {

        sealed class PacketBinder : SerializationBinder

        {

            public override Type BindToType(string assemblyName, string typeName)

            {

                Type returntype = null;

                assemblyName = Assembly.GetExecutingAssembly().FullName;

     

                string sharedAssemblyName = "SharedAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";

                typeName = typeName.Replace(sharedAssemblyName, assemblyName);

     

                returntype = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));

                return returntype;

            }

        }

    }

     

    LocalClient.cs

    using System;

    using System.IO;

    using System.Net.Sockets;

    using System.Runtime.Serialization.Formatters.Binary;

     

    namespace Unity.Network

    {

        public class LocalClient

        {

            private const string LocalIp = "127.0.0.1";

            public const int PortNumber = 10001;

            private const int BufferSize = 2048;

     

            private NetworkStream _stream;

            public NetworkStream Stream

            {

                get { return _stream; }

            }

     

            private readonly BinaryFormatter _formatter;

     

            private TcpClient _client;

            private byte[] _buffer;

     

            public string UserName { get; set; }

     

            public event Connected OnConnected;

            public event Disconnected OnDisconnected;

            public event ConnectError OnConnectError;

            public event ReceiveObject OnReceiveObject;

     

            /// <summary>

            /// 클라이언트용 생성자

            /// </summary>

            public LocalClient() : this(null)

            {

                

            }

     

            /// <summary>

            /// 서버용 생성자

            /// </summary>

            /// <param name="client">이미 생성된 TcpClient</param>

            public LocalClient(TcpClient client)

            {

                _client = client;

     

                _formatter = new BinaryFormatter();

                _formatter.Binder = new PacketBinder();

     

                _buffer = new byte[BufferSize];

            }

     

            public void Start()

            {

                if (_client != null)

                {

                    _stream = _client.GetStream();

     

                    //서버 -> 클라이언트

                    BeginRead();

                }

                else

                {

                    //클라이언트 -> 서버

                    StartClient();

                }

            }

     

            private void StartClient()

            {

                //클라이언트 -> 서버

                _client = new TcpClient();

     

                try

                {

                    _client.BeginConnect(LocalIp, PortNumber, EndConnect, null);

                }

                catch (SocketException ex)

                {

                    if (OnConnectError != null)

                        OnConnectError(ex);

                }

            }

     

            private void EndConnect(IAsyncResult result)

            {

                try

                {

                    _client.EndConnect(result);

                    _stream = _client.GetStream();

     

                    if (OnConnected != null)

                        OnConnected(this);

     

     

                    BeginRead();

                }

                catch (SocketException ex)

                {

                    if (OnConnectError != null)

                        OnConnectError(ex);

                }

            }

     

            private void BeginRead()

            {

                _stream.BeginRead(_buffer, 0, BufferSize, new AsyncCallback(ReadObject), null);

            }

     

            public void Close()

            {

                _stream.Close();

                _client.Close();

            }

     

            private void ReadObject(IAsyncResult result)

            {

                int readSize = 0;

     

                try

                {

                    lock (_stream)

                    {

                        readSize = _stream.EndRead(result);

                    }

     

                    if (readSize < 1)

                        throw new Exception("Disconnect");

     

     

                    Packet packet = new Packet();

                    using (MemoryStream stream = new MemoryStream(_buffer))

                    {

                        packet = (Packet)_formatter.Deserialize(stream);

                    }

     

                    if (OnReceiveObject != null)

                        OnReceiveObject(this, packet);

     

     

                    lock (_stream)

                    {

                        BeginRead();

                    }

                }

                catch(Exception ex)

                {

                    if (OnDisconnected != null)

                        OnDisconnected(this, ex);

                }

            }

     

            public void SendPacket(Packet packet)

            {

                byte[] data = null;

                try

                {

                    using (MemoryStream stream = new MemoryStream())

                    {

                        _formatter.Serialize(stream, packet);

     

                        data = stream.ToArray();

                    }

     

                    if (data == null || data.Length < 1)

                        return;

     

                    _stream.Write(data, 0, data.Length);

                    _stream.Flush();

                }

                catch

                {

                    

                }//try

            }

        }

     

        public delegate void Connected(LocalClient client);

        public delegate void Disconnected(LocalClient client, Exception ex);

        public delegate void ConnectError(SocketException ex);

        public delegate void ReceiveObject(LocalClient client, Packet packet);

    }

     

    NetMultiServer.cs

    using System;

    using System.Collections.Generic;

    using System.Net.Sockets;

    using System.Threading;

    using Unity.Network;

     

    namespace CsConnector

    {

        public class NetMultiServer

        {        

            private readonly TcpListener _listener;

     

            private readonly Dictionary<string, LocalClient> _clientTable;

            private readonly Thread _listenerThread;

     

            public NetMultiServer()

            {

                _clientTable = new Dictionary<string, LocalClient>();

     

                _listener = new TcpListener(System.Net.IPAddress.Any, LocalClient.PortNumber);

                _listenerThread = new Thread(new ThreadStart(DoListen));

            }

     

            public void Start()

            {

                _listenerThread.Start();

            }

     

            public void Close()

            {

                _listener.Stop();

            }

     

            private void DoListen()

            {

                try

                {

                    _listener.Start();

     

                    do

                    {

                        TcpClient tcpClient = _listener.AcceptTcpClient();

     

                        LocalClient localClient = new LocalClient(tcpClient);

                        localClient.OnReceiveObject += ReceiveObject;

                        localClient.Start();

                    }

                    while (true);

                }

                catch (Exception)

                {

     

                }//try

            }

     

            private void ReceiveObject(LocalClient client, Packet packet)

            {

                if (packet == null)

                    return;

     

                switch (packet.Type)

                {

                    case PacketType.Connect: OnConnected(client, packet); break;

                }

            }

     

            private void OnConnected(LocalClient client, Packet packet)

            {

                Connect connect = packet as Connect;

                if (connect == null)

                    return;

     

     

                client.UserName = connect.UserName;

                _clientTable.Add(client.UserName, client);

            }

     

            private void SendPacket(LocalClient client, Packet packet)

            {

                client.SendPacket(packet);

            }

        }

    }

     

    NetClient.cs

    using System;

    using Unity.Network;

    using UnityEngine;

     

    public class NetClient

    {

        private const string UserName = "UnityClient";

     

        private LocalClient _client;

     

        public event Chat OnChat;

     

        public NetClient()

        {

            

        }

     

        public void Start()

        {

            _client = new LocalClient();

            _client.OnConnected += Connected;

            _client.Start();

        }

     

        public void Close()

        {

            _client.Close();

        }

     

        private void Connected(LocalClient client)

        {

            Connect connect = new Connect()

            {

                Type = PacketType.Connect,

                UserName = UserName,

            };

     

            _client.UserName = UserName;

            _client.SendPacket(connect);

        }

     

        private void ConnectError(Exception ex)

        {

            Debug.Log("접속 에러\n" + ex.ToString());

        }

     

        private void ReceiveObject(LocalClient client, Packet packet)

        {

            if (packet == null)

                return;

     

            switch (packet.Type)

            {

                case PacketType.Chat: OnChatMessage(client, packet); break;

            }

        }

     

        private void OnChatMessage(LocalClient client, Packet packet)

        {

            ChatMessage message = packet as ChatMessage;

            if (message == null)

                return;

     

            if (OnChat != null)

                OnChat(message.Message);

        }

     

        private void SendPacket(LocalClient client, Packet packet)

        {

            client.SendPacket(packet);

        }

     

        public delegate void Chat(string message);

    }