네트워크 및 보안/네트워크 프로그래밍 with C#

3. 에코 클라이언트 만들기

언제나휴일 2019. 1. 4. 14:20
반응형

3. 에코 클라이언트 만들기



 앞에서 TCP 에코 서버를 구현했는데 이번에는 TCP 에코 클라이언트를 구현합시다.


 에코 클라이언트도 콘솔 응용프로그램 만들기로 할게요. 먼저 콘솔 응용프로그램(콘솔 앱)을 만드세요. 그리고 에코 클라이언트를 정의할 EchoClient 이름의 클래스를 추가하세요. 여기에서는 EchoClient를 별도의 라이브러리로 제작할 수 있게 클래스의 접근 수준을 public으로 지정할게요.

namespace 에코_클라이언트

{

    public class EchoClient

    {

    }

}

 

 EchoClientEchoServer처럼 클라이언트가 연결 시도할 때 필요한 서버의 IP 주소와 포트를 입력인자로 전달하여 개체를 생성합니다. 그리고 이는 비대칭 자동 속성으로 정의한 멤버에 설정하게 작성하세요.

        public string IPStr

        {

            get;

            private set;

        }

        public int Port

        {

            get;

            private set;

        }

        public EchoClient(string ipstr, int port)

        {

            IPStr = ipstr;

            Port = port;

        }

 

 클라이언트를 동작시키는 부분은 Start 메서드로 만들기로 할게요.

        public void Start()

        {

 

 클라이언트도 네트워크 통신을 위해 소켓을 생성합니다. 에코 서버와 연결하여 통신할 것이므로 에코 서버처럼 네트워크 주소체계와 소켓 타입 및 프로토콜을 입력 인자로 전달합니다. 네트워크 주소체계는 IPv4이며 소켓 타입은 스트림, 프로토콜은 TCP입니다.

            //소켓 생성

            Socket sock = new Socket(

                AddressFamily.InterNetwork,

                SocketType.Stream,

                ProtocolType.Tcp

                );

 

 클라이언트는 네트워크 인터페이스와 결합하는 Bind 메서드를 선택적으로 호출할 수 있습니다. 일반적으로 Bind 메서드 호출을 하지 않고 연결 요청 시에 사용 가능한 포트와 결합한 후 연결합니다. 만약 클라이언트에서도 특정 포트와 연결을 원한다면 Bind 메서드를 호출할 수는 있습니다. 여기에서는 바로 연결 요청하기로 할게요. 연결 요청은 Connect 메서드이며 서버의 단말 정보를 전달해야 합니다.

            //연결 요청

            //연결할 서버의 소켓 주소를 전달해야 함

            IPAddress ipaddr = IPAddress.Parse(IPStr);

            IPEndPoint servpt = new IPEndPoint(ipaddr, Port);

            sock.Connect(servpt);

 

 메시지를 전송하기 위한 버퍼를 생성하세요.

            //서버와 메시지 주고 받기

            byte[] packet = new byte[1024];

 

 에코 서버에서 클라이언트로부터 "Exit" 문자열을 받기 전까지 수신한 메시지를 전송하는 형태로 에코 서비스를 구현하였습니다. 이에 맞게 클라이언트도 작성합니다. 무한 루프로 표현할게요.

            while (true)

            {

 

 먼저 사용자로부터 전송할 문자열을 입력받습니다.

                Console.Write(":");

                string msg = Console.ReadLine();

 

 전송할 문자열을 메모리 스트림 개체와 BinaryWriter를 통해 버퍼를 채웁니다.

                MemoryStream ms = new MemoryStream(packet);

                BinaryWriter bw = new BinaryWriter(ms);

                bw.Write(msg);

                bw.Close();

                ms.Close();

 

 

  이제 전송할 문자열을 채운 버퍼를 Send 메서드를 호출하여 전송합니다.

                sock.Send(packet);

 

 Receive 메서드를 호출하여 에코 메시지를 수신합니다. 만약 서버에서 연결을 닫는다면 수신한 바이트 수가 0입니다. 따라서 Receive 메서드의 반환 결과가 0보다 작거나 같다면 서버에서 연결을 닫았거나 문제가 발생한 것이므로 루프를 탈출합니다.

                if (sock.Receive(packet) <= 0)

                {

                    break;

                }

 

 수신한 메시지를 문자열로 변환하여 콘솔 화면에 출력하세요.

                ms = new MemoryStream(packet);

                BinaryReader br = new BinaryReader(ms);

                string rstr = br.ReadString();

                Console.WriteLine("§:{0}", rstr);

                ms.Close();

                br.Close();

            }

 

 작업이 끝났으면 소켓을 닫습니다.

            sock.Close();//연결 닫기

        }

 

 이제 Program 클래스의 진입점인 Main 메서드를 작성합시다. 먼저 연결할 서버의 단말 정보를 입력받습니다.

         Console.Write("연결할 에코 서버 IPv4 주소:");

            string ipstr = Console.ReadLine();

            int port = 13000;

            Console.Write("포트 번호:");

            int.TryParse(Console.ReadLine(), out port);

            Console.WriteLine("... IPv4:{0} 포트 번호:{1} ...", ipstr, port);

 

 에코 클라이언트를 생성하고 가동시키세요.

            try

            {

                EchoClient ec = new EchoClient(ipstr, port);

                ec.Start();

            }

            catch

            {

                Console.WriteLine("연결 실패하였습니다.");

            }

 

//EchoClient.cs

using System;

using System.IO;

using System.Net;

using System.Net.Sockets;

 

namespace 에코_클라이언트

{

    public class EchoClient

    {

        public string IPStr

        {

            get;

            private set;

        }

        public int Port

        {

            get;

            private set;

        }

 

        public EchoClient(string ipstr, int port)

        {

            IPStr = ipstr;

            Port = port;

        }

        public void Start()

        {

            //소켓 생성

            Socket sock = new Socket(

                AddressFamily.InterNetwork,

                SocketType.Stream,

                ProtocolType.Tcp

                );

            //연결 요청

            //연결할 서버의 소켓 주소를 전달해야 함

            IPAddress ipaddr = IPAddress.Parse(IPStr);

            IPEndPoint servpt = new IPEndPoint(ipaddr, Port);

            sock.Connect(servpt);

 

            //서버와 메시지 주고 받기

            byte[] packet = new byte[1024];

            while (true)

            {

                Console.Write(":");

                string msg = Console.ReadLine();

                MemoryStream ms = new MemoryStream(packet);

                BinaryWriter bw = new BinaryWriter(ms);

                bw.Write(msg);

                bw.Close();

                ms.Close();

 

                sock.Send(packet);

 

 

                if (sock.Receive(packet) <= 0)

                {

                    break;

                }

                ms = new MemoryStream(packet);

                BinaryReader br = new BinaryReader(ms);

                string rstr = br.ReadString();

                Console.WriteLine("§:{0}", rstr);

                ms.Close();

                br.Close();

            }

 

            sock.Close();//연결 닫기

        }

    }

}

 

//Prgoram.cs

using System;

 

namespace 에코_클라이언트

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.Write("연결할 에코 서버 IPv4 주소:");

            string ipstr = Console.ReadLine();

            int port = 13000;

            Console.Write("포트 번호:");

            int.TryParse(Console.ReadLine(), out port);

            Console.WriteLine("... IPv4:{0} 포트 번호:{1} ...", ipstr, port);

 

            try

            {

                EchoClient ec = new EchoClient(ipstr, port);

                ec.Start();

            }

            catch

            {

                Console.WriteLine("연결 실패하였습니다.");

            }

        }

    }

}

 


반응형

'네트워크 및 보안 > 네트워크 프로그래밍 with C#' 카테고리의 다른 글

2. 에코 서버 만들기  (0) 2019.01.04
1. TCP 통신 절차  (0) 2019.01.04