12. 프락스 패턴(Proxy Pattern) - 원격지 프락시
"본문 내용"은 언제나 휴일 본 사이트에 있습니다.
서버 측 코드
▶ 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("자동 모드로 변환되었습니다.");
}
}
}
}
▶ 실행 결과
'.NET > 설계 패턴(C#)' 카테고리의 다른 글
[설계 패턴 C#]14. 프락스 패턴(Proxy Pattern) - 보호용 프락시 (0) | 2016.06.24 |
---|---|
[설계 패턴 C#]13. 프락스 패턴(Proxy Pattern) - 가상 프락시 (0) | 2016.06.24 |
[설계 패턴 C#] 11. 플라이급 패턴(Flyweight Pattern) (0) | 2016.06.23 |
[설계 패턴 C#] 10. 퍼샤드 패턴 (0) | 2016.06.09 |
[설계 패턴 C#] 9. 장식자 패턴 (0) | 2016.06.09 |