.NET/네트워크 프로그래밍 C#

TCP 통신 – Echo 서버 클래스 구현, 이벤트 정의 및 콜백 처리 [C#]

언제나휴일 2020. 6. 26. 12:34
반응형

 

Echo 서버 클래스 구현 동영상 강의

 

AcceptedEventArgs.cs

using System;
using System.Net;

namespace 에코_서버_응용___클래스로_정의
{
    public delegate void AcceptedEventHandler(object sender, AcceptedEventArgs e);
    public class AcceptedEventArgs:EventArgs
    {
        public IPEndPoint RemoteEP
        {
            get;
            private set;
        }
        public string IPStr
        {
            get
            {
                return RemoteEP.Address.ToString();
            }
        }
        public int Port
        {
            get
            {
                return RemoteEP.Port;
            }
        }
        public AcceptedEventArgs(IPEndPoint remote_ep)
        {
            RemoteEP = remote_ep;
        }
    }
}

ClosedEventArgs.cs

using System;
using System.Net;

namespace 에코_서버_응용___클래스로_정의
{
    public delegate void ClosedEventHandler(object sender, ClosedEventArgs e);
    public class ClosedEventArgs:EventArgs
    {
        public IPEndPoint RemoteEP
        {
            get;
            private set;
        }
        public string IPStr
        {
            get
            {
                return RemoteEP.Address.ToString();
            }
        }
        public int Port
        {
            get
            {
                return RemoteEP.Port;
            }
        }
        public ClosedEventArgs(IPEndPoint remote_ep)
        {
            RemoteEP = remote_ep;
        }
    }
}

RecevedMsgEventArgs.cs

using System;
using System.Net;

namespace 에코_서버_응용___클래스로_정의
{
    public delegate void RecvedMsgEventHandler(object sender, RecvedMsgEventArgs e);
    public class RecvedMsgEventArgs:EventArgs
    {
        public IPEndPoint RemoteEP
        {
            get;
            private set;
        }
        public string IPStr
        {
            get
            {
                return RemoteEP.Address.ToString();
            }
        }
        public int Port
        {
            get
            {
                return RemoteEP.Port;
            }
        }
        public string Msg
        {
            get;
            private set;
        }
        public RecvedMsgEventArgs(IPEndPoint remote_ep,string msg)
        {
            RemoteEP = remote_ep;
            Msg = msg;
        }
    }
}

EchoServer.cs

using System.IO;
using System.Net;
using System.Net.Sockets;

namespace 에코_서버_응용___클래스로_정의
{
    public class EchoServer
    {
        public event AcceptedEventHandler AcceptedEventHandler = null;
        public event ClosedEventHandler ClosedEventHandler = null;
        public event RecvedMsgEventHandler RecvedMsgEventHandler = null;
        public string IPStr
        {
            get;
            private set;
        }
        public int Port
        {
            get;
            private set;
        }

        public EchoServer(string ipstr, int port)
        {
            IPStr = ipstr;
            Port = port;
        }

        Socket sock = null;
        public bool Start()
        {
            try
            {
                sock = new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Stream,
                    ProtocolType.Tcp
                    );//소켓 생성

                //인터페이스와 결합
                IPAddress addr = IPAddress.Parse(IPStr);
                IPEndPoint iep = new IPEndPoint(addr, Port);
                sock.Bind(iep);

                //백로그 큐 크기 설정
                sock.Listen(5);
                AcceptLoopAsyn();
                return true;
            }
            catch
            {
                return false;
            }
        }
        public void Close()
        {
            if (sock != null)
            {
                try
                {
                    sock.Close();
                }
                catch
                {
                }
            }
        }

        delegate void AcceptDele();
        private void AcceptLoopAsyn()
        {
            AcceptDele dele = AcceptLoop;
            dele.BeginInvoke(null, null);
        }
        void AcceptLoop()
        {
            Socket dosock = null;
            while (true)
            {
                dosock = sock.Accept();
                DoItAsync(dosock);
            }
        }

        delegate void DoItDele(Socket dosock);
        private void DoItAsync(Socket dosock)
        {
            DoItDele dele = DoIt;
            dele.BeginInvoke(dosock, null, null);
        }
        private void DoIt(Socket dosock)
        {
            IPEndPoint remote_ep = dosock.RemoteEndPoint as IPEndPoint;
            if(AcceptedEventHandler != null)
            {
                AcceptedEventHandler(this, new AcceptedEventArgs(remote_ep));
            }

            try
            {
                byte[] packet = new byte[1024];                
                while (true)
                {
                    dosock.Receive(packet);
                    MemoryStream ms = new MemoryStream(packet);
                    BinaryReader br = new BinaryReader(ms);
                    string msg = br.ReadString();
                    br.Close();
                    ms.Close();
                    if(RecvedMsgEventHandler != null)
                    {
                        RecvedMsgEventHandler(this, new RecvedMsgEventArgs(remote_ep, msg));
                    }                    
                    dosock.Send(packet);
                }
            }
            catch
            {

            }
            finally
            {                
                dosock.Close();
                if (ClosedEventHandler != null)
                {
                    ClosedEventHandler(this, new ClosedEventArgs(remote_ep));
                }
            }
        }

    }
}

Program.cs

using System;

namespace 에코_서버_응용___클래스로_정의
{
    class Program
    {
        static void Main(string[] args)
        {
            EchoServer es = new EchoServer([서버 IP 주소], 서버 Port);
            es.RecvedMsgEventHandler += Es_RecvedMsgEventHandler;
            es.AcceptedEventHandler += Es_AcceptedEventHandler;
            es.ClosedEventHandler += Es_ClosedEventHandler;
            if(es.Start()==false)
            {
                Console.WriteLine("서버 가동 실패");
                return;
            }
            Console.ReadKey();
            es.Close();
        }

        private static void Es_ClosedEventHandler(object sender, ClosedEventArgs e)
        {
            Console.WriteLine("{0}:{1}에서 연결을 닫음",e.IPStr,e.Port);
        }

        private static void Es_AcceptedEventHandler(object sender, AcceptedEventArgs e)
        {
            Console.WriteLine("{0}:{1}에서 연결 했음", e.IPStr, e.Port);
        }

        private static void Es_RecvedMsgEventHandler(object sender, RecvedMsgEventArgs e)
        {
            Console.WriteLine("{0}:{1} →{2}", e.IPStr, e.Port,e.Msg);
        }
    }
}
반응형

'.NET > 네트워크 프로그래밍 C#' 카테고리의 다른 글

.NET 리모팅  (0) 2020.07.02
TCP 통신 – echo 서버 및 클라이언트 구현 [C#]  (0) 2020.06.25