| 일 | 월 | 화 | 수 | 목 | 금 | 토 | 
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 
| 9 | 10 | 11 | 12 | 13 | 14 | 15 | 
| 16 | 17 | 18 | 19 | 20 | 21 | 22 | 
| 23 | 24 | 25 | 26 | 27 | 28 | 29 | 
| 30 | 
                            Tags
                            
                        
                          
                          - 원격 제어 프로그램
- 동영상 강의
- 표준 입출력
- 언제나휴일
- 실습으로 다지는 c#
- 소스 코드
- 실습
- 안드로이드 앱 개발
- 언제나 휴일
- C++
- 추천
- c#
- 소켓 통신
- 네트워크 프로그래밍
- c언어
- 충남 천안
- 독립기념관
- 알고리즘
- 무료 동영상 강의
- 강의
- 표준 라이브러리 함수
- 산책하기 좋은 곳
- 캡슐화
- 유튜브 동영상 강의
- 클래스 다이어그램
- 졸업 작품 소재
- 파이썬
- Windows Forms
- 동영상
- 프로젝트
                            Archives
                            
                        
                          
                          - Today
- Total
프로그래밍 언어 및 기술 [언제나휴일]
TCP 통신 – Echo 서버 클래스 구현, 이벤트 정의 및 콜백 처리 [C#] 본문
1. 유튜브 동영상 강의
이번 실습은 Echo 서버 클래스를 구현하는 실습이예요.
여기서 만들 서버 클래스는 라이브러리로 제작하기 위한 목적으로 사전 작업하는 것이예요.
서버 클래스를 사용하는 곳에서 연결 수락 및 닫기, 메시지 수신에 관한 이벤트 처리를 할 수 있게 정의합니다. 대리자 및 이벤트 인자를 정의하고 Echo 서버에 이벤트 멤버를 정의하여 콜백 처리를 하는 것이죠.
2. 연결 수락 이벤트 인자 및 대리자 소스 코드
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;
        }
    }
}3. 연결 닫기 이벤트 인자 및 대리자 소스 코드
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;
        }
    }
}4. 메시지 수신 이벤트 인자 및 대리자 소스 코드
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;
        }
    }
}5. Echo 서버 클래스 소스 코드
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));
                }
            }
        }
    }
}6. 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);
        }
    }
}7. Echo 클라이언트 프로젝트의 Program.cs 소스 코드
다음은 이전 강의에서 작성했던 Echo 클라이언트의 소스 코드입니다.
이번 실습에서는 별도의 클라이언트를 제작하지 않고 이전 강의에서 작성한 것을 사용합니다.
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace 에코_클라이언트_응용
{
    class Program
    {
        static void Main(string[] args)
        {           
            Socket sock  = new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Stream,
                    ProtocolType.Tcp
                    );//소켓 생성
            //인터페이스 결합(옵션)
            //연결
            IPAddress addr = IPAddress.Parse([서버 IP 주소]);
            IPEndPoint iep = new IPEndPoint(addr, [서버 Port 번호]);
            sock.Connect(iep);
            string str;
            string str2;
            byte[] packet = new byte[1024];
            byte[] packet2 = new byte[1024];
            while (true)
            {
                Console.Write("전송할 메시지:");
                str = Console.ReadLine();
                MemoryStream ms = new MemoryStream(packet);
                BinaryWriter bw = new BinaryWriter(ms);
                bw.Write(str);
                bw.Close();
                ms.Close();
                sock.Send(packet);
                if(str == "exit")
                {
                    break;
                }
                sock.Receive(packet2);
                MemoryStream ms2 = new MemoryStream(packet2);
                BinaryReader br = new BinaryReader(ms2);
                str2 = br.ReadString();
                Console.WriteLine("수신한 메시지:{0}", str2);
                br.Close();
                ms2.Close();
            }
            sock.Close();//소켓 닫기
        }
    }
}'C# > 네트워크 프로그래밍 C#' 카테고리의 다른 글
| P2P 메신저 – 인증 서비스 구현 및 마무리[C#] (0) | 2024.01.09 | 
|---|---|
| .NET 리모팅 [C#] (0) | 2024.01.09 | 
| P2P 메신저 – 파일 송수신 기능 구현 [C#] (0) | 2024.01.08 | 
| P2P 메신저 - 파일 수신 서버 구현 [C#] (0) | 2024.01.07 | 
| P2P 메신저 - 파일 전송 클라이언트 구현 [C#] (0) | 2024.01.07 | 
| P2P 메신저 – 숏 메시지 송수신 예광탄 구현하기 [C#] (1) | 2024.01.06 | 
| TCP 통신 – echo 서버 및 클라이언트 구현 [네트워크 프로그래밍 C#] (2) | 2024.01.04 | 
 
                   
                   
                  