.NET/설계 패턴(C#)

[설계 패턴 C#]12. 프락스 패턴(Proxy Pattern) - 원격지 프락시

언제나휴일 2016. 6. 23. 13:28
반응형

12. 프락스 패턴(Proxy Pattern) - 원격지 프락시


RemoteClient.zip

RemoteProxy.zip

"본문 내용"은 언제나 휴일 본 사이트에 있습니다.

서버 측 코드

▶ ITake.cs

namespace RemoteClient

{

    interface ITake //실제 개체인 카메라가 수행할 수 있는 기능 약속

    {

        string TakeAPicture();

        void ChangeMode(bool mode);

        bool GetMode();

    }

    enum MsgId //실제 개체에 내릴 수 있는 명령 종류

    {

        TAKE=1,

        CHANGE,

        GET

    }

}


▶ Camera.cs

using System;

namespace RemoteProxy

{

    class Camera:ITake

    {

        bool mode = false; //true: 수동 모드, false: 자동 모드


        public string TakeAPicture()

        {

            Console.WriteLine("사진을 찍습니다.");

            if (mode)

            {

                return "수동 모드로 찍힌 사진";

            }

            return "자동 모드로 찍힌 사진";

        }

        public void ChangeMode(bool mode)

        {

            this.mode = mode;

            if (mode)

            {

                Console.WriteLine("수동 모드로 변환되었습니다.");

            }

            else

            {

                Console.WriteLine("자동 모드로 변환되었습니다.");

            }

        }

        public bool GetMode()

        {

            if (mode)

            {

                Console.WriteLine("수동 모드입니다.");

            }

            else

            {

                Console.WriteLine("자동 모드입니다.");

            }

            return mode;

        }

    }

}


▶ ListenServer.cs

using System.Net.Sockets;

using System.Net;

using System.Threading;

namespace RemoteProxy

{

    static class ListenServer //클라이언트 연결을 수락하는 서버

    {

        static public void StartListen(ITake itake)

        {

            Socket sock = new Socket(AddressFamily.InterNetwork,

                                               SocketType.Stream, ProtocolType.Tcp);

            sock.Bind(new IPEndPoint(IPAddress.Any, 10200));

            sock.Listen(5);

            while (true)

            {

                Stub stub = new Stub(sock.Accept(), itake); //클라이언트와 통신을 담당

                Thread thread = new Thread(stub.Do);

                thread.Start();

            }

        }

    }

}


▶ Stub.cs

using System;

using System.Net.Sockets;

using System.Text;

namespace RemoteProxy

{

    class Stub //클라이언트 명령을 받아 실제 개체를 제어하는 서버 측 클래스

    {

        Socket dosock; //클라이언트와 통신할 소켓

        ITake itake; //클라이언트의 요청에 맞게 기능을 수행할 실제 개체


        public Stub(Socket dosock, ITake itake)

        {

            this.dosock = dosock;

            this.itake = itake;

        }

        private void GetProc()

        {

            bool mode= itake.GetMode(); //실제 개체에게 모드를 얻어옴

            byte[] msg = new byte[1]; //모드를 전송할 때 필요한 버퍼

            msg[0] = Convert.ToByte(mode);

            dosock.Send(msg);  //요청한 모드를 전송

        }

        private void TakeProc()

        {

            string picture = itake.TakeAPicture(); //실제 개체로 사진을 찍음

            byte[] msg = Encoding.UTF8.GetBytes(picture); //사진을 전송할 버퍼로 변환

            dosock.Send(msg); //실제 개체가 찍은 사진을 전송

        }

        private void ChangeProc()

        {

            byte[] buffer = new byte[1]; //모드를 수신할 때 필요한 버퍼

            bool mode;

            dosock.Receive(buffer); //요청한 모드를 받음


            mode = Convert.ToBoolean(buffer[0]);

            itake.ChangeMode(mode); //실제 개체에게 모드 변경 요청

        }


        public void Do()

        {

            byte[] buffer = new byte[1];

            int n = dosock.Receive(buffer); //명령 종류를 얻어옴


            MsgId msgid = (MsgId)buffer[0];

            Console.WriteLine(msgid);


            switch (msgid) //수신한 명령에 맞는 기능 수행

            {

                case MsgId.TAKE: TakeProc(); break;

                case MsgId.CHANGE: ChangeProc(); break;

                case MsgId.GET: GetProc(); break;

            }

            dosock.Close();

        }

    }

}


▶ Program.cs

namespace RemoteProxy

{

    class Program

    {

        static void Main(string[] args)

        {

            Camera camera = new Camera(); //실제 개체인 카메라 생성


            //실제 개체를 제어를 요청할 클라이언트를 대기하는 서버 가동

            ListenServer.StartListen(camera);  

        }

    }

}


클라이언트 측 코드

▶ RemoteController.cs

using System;

using System.Text;

using System.Net.Sockets;

namespace RemoteClient

{

    class RemoteController:ITake

    {

        public string TakeAPicture()

        {

            Socket sock = Connect(MsgId.TAKE);

            byte[] buffer = new byte[256];

            int n = sock.Receive(buffer);

            sock.Close();

            return Encoding.UTF8.GetString(buffer, 0, n);

        }

        public void ChangeMode(bool mode)

        {

            Socket sock = Connect(MsgId.CHANGE);            

            byte[] msg = new byte[1];

            msg[0] = Convert.ToByte(mode);

            sock.Send(msg);

            sock.Close();

        }

        public bool GetMode()

        {

            Socket sock = Connect(MsgId.GET);

            byte[] buffer= new byte[1];

            int n = sock.Receive(buffer);

            return Convert.ToBoolean(buffer[0]);

        }

        Socket Connect(MsgId msgid)

        {            

            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            

            sock.Connect("서버 IP 주소로 바꾸세요.",10200);

            byte[] msg = new byte[1];

            msg[0] = (byte)msgid;

            sock.Send(msg);

            return sock;

        }

    }

}


▶ Program.cs

using System;

namespace RemoteClient

{

    class Program

    {

        static void Main(string[] args)

        {            

            RemoteController remocon = new RemoteController();

            string s = remocon.TakeAPicture();

            Console.WriteLine(s);

            remocon.ChangeMode(true);            

            s = remocon.TakeAPicture();

            Console.WriteLine(s);

            remocon.ChangeMode(false);

            s = remocon.TakeAPicture();

            Console.WriteLine(s);

            bool mode = remocon.GetMode();

            if (mode)

            {

                Console.WriteLine("수동 모드로 변환되었습니다.");

            }

            else

            {

                Console.WriteLine("자동 모드로 변환되었습니다.");

            }

        }

    }

}


▶ 실행 결과

원격지 프락시 실행 화면


반응형