이제 원격 제어 컨트롤러를 만들어 봅시다. 먼저 공통으로 사용할 부분을 작성할게요.
public static class NetworkInfo {
이미지 서버 포트 접근자를 제공합시다. 여기에서 하드 코딩할게요.
public static short ImgPort //이미지 서버 포트 { get { return 20004; } }
원격 제어 요청 포트 접근자를 제공합시다.
public static short SetupPort//원격 제어 요청 포트 { get { return 20002; } }
이벤트 서버 포트 접근자를 제공합시다.
public static short EventPort//이벤트 서버 포트 { get { return 20010; } }
로컬 호스트의 디폴트 IP 주소 문자열 접근자를 제공합시다.
public static string DefaultIP { get {
먼저 호스트 이름을 구합니다.
string host_name = Dns.GetHostName(); //호스트 이름 구하기
호스트 이름으로 호스트 엔트리를 구합니다.
//호스트 엔트리 구하기 IPHostEntry host_entry = Dns.GetHostEntry(host_name);
호스트 엔트리에 있는 주소를 반복해서 확인합니다.
//호스트 주소 목록을 반복 foreach (IPAddress ipaddr in host_entry.AddressList) {
만약 주소 체계가 InterNetwork일 때 IP 주소 문자열을 반환하세요.
//주소 체계가 InterNetwork일 때 if (ipaddr.AddressFamily == AddressFamily.InterNetwork) { return ipaddr.ToString();//IP 주소 문자열 반환 } }
없을 때 빈 문자열을 반환하세요.
return string.Empty;//빈 문자열 반환 } } }
이번에는 원격 제어하는 컨트롤러를 만들어 봅시다.
public class Controller {
원격 제어 컨트롤러는 단일체 패턴으로 정의할 것입니다. 이를 위해 정적 개체를 위한 정적 멤버 필드를 선언하세요.
static Controller singleton; //단일체
단일체에 접근할 수 있게 접근자를 제공하세요.
public static Controller Singleton //단일체 접근자 { get { return singleton; } }
단일체는 정적 생성자에서 생성하세요. 정적 생성자는 접근 지정자를 표시할 수 없습니다. 그리고 정적 생성자는 해당 형식을 사용하는 것보다 먼저 수행하는 것을 보장하며 개발자가 직접 호출하는 대상이 아닙니다.
static Controller()//정적 생성자 { singleton = new Controller();//단일체 생성 }
단일체 외에 다른 개체를 생성할 수 없게 생성자의 접근 가시성을 private으로 지정합니다.
private Controller()//접근 가시성이 private인 기본 생성자 { }
원격 제어 컨트롤러는 원격 제어 호스트 이미지를 수신하기 위해 이미지 수신 서버가 필요합니다.
ImageServer img_sever = null; //이미지 수신 서버
원격 제어 컨트롤러는 제어하기 위해 키보드와 마우스 이벤트를 원격 제어 호스트에게 전송해야 합니다. 이 때 사용할 이벤트 전송 클라이언트를 사용할 것예요.
SendEventClient sce = null; //키보드, 마우스 제어 이벤트 전송 클라이언트
원격 제어 호스트로부터 이미지를 수신하며 이를 폼에게 전달하여 시각화할 수 있게 해 주어야 합니다.
public event RecvImageEventHandler RecvedImage = null;//이미지 수신 이벤트
원격 제어 호스트 IP도 필요하겠죠.
string host_ip; //원격 제어 호스트 IP 문자열
폼에서 이벤트 전송 클라이언트에 접근할 수 있게 접근자를 제공합시다.
public SendEventClient SendEventClient //이벤트 전송 클라이언트 접근자 { get { return sce; } }
로컬 호스트의 IP 문자열을 제공하는 접근자를 추가하세요.
public string MyIP//로컬 IP문자열 접근자 { get { return NetworkInfo.DefaultIP; } }
원격 컨트롤러를 시작하는 메서드를 정의합시다.
public void Start(string host_ip) {
입력 인자로 받은 원격 제어 호스트 IP 문자열을 설정하세요.
this.host_ip = host_ip;
이미지 서버를 가동합니다.
img_sever = new ImageServer(MyIP, NetworkInfo.ImgPort);//이미지 서버 가동
이미지 서버가 이미지를 수신하였을 때의 이벤트를 구독 요청하세요.
//구독 요청 img_sever.RecvedImage += new RecvImageEventHandler(img_sever_RecvedImage);
이제 원격 제어 호스트에게 원격 제어하겠다고 요청합니다.
SetupClient.Setup(host_ip, NetworkInfo.SetupPort); //원격 제어 요청 }
이미지 수신 이벤트 핸들러를 작성합시다.
//이미지 수신 이벤트 핸들러 void img_sever_RecvedImage(object sender, RecvImageEventArgs e) {
이미지 수신 이벤트 핸들러에서는 구독자(폼)에게 이벤트를 By Pass합니다.
if (RecvedImage != null)//이미지 수신 이벤트 구독자가 있을 때 { RecvedImage(this, e);//이미지 수신 이벤트 게시(By Pass) } }
이벤트 클라이언트를 시작하는 메서드를 정의합시다.
public void StartEventClient() {
이벤트 송신 클라이언트 개체를 생성합니다.
sce = new SendEventClient(host_ip, NetworkInfo.EventPort); //이벤트 송신 클라이언트 개체 생성 }
원격 제어 컨트롤러를 멈추는 메서드를 정의합시다.
public void Stop()//원격 컨트롤러 멈춤 { if (img_sever != null) {
이미지 서버를 닫습니다.
img_sever.Close();//이미지 서버 닫기
이미 멈춘 상태에서 다시 닫지 않게 이미지 서버를 null로 설정하세요.
img_sever = null; } } }
다음은 이번 실습에서 작성한 소스 코드입니다.
using System.Net; using System.Net.Sockets; namespace 원격제어기 { public class Controller { static Controller singleton; public static Controller Singleton { get { return singleton; } } static Controller() { singleton = new Controller(); } private Controller() { } ImageServer img_sever = null; SendEventClient sce = null; public event RecvImageEventHandler RecvedImage = null; string host_ip; public SendEventClient SendEventClient { get { return sce; } } public string MyIP { get { string host_name = Dns.GetHostName(); IPHostEntry host_entry = Dns.GetHostEntry(host_name); foreach (IPAddress ipaddr in host_entry.AddressList) { if (ipaddr.AddressFamily == AddressFamily.InterNetwork) { return ipaddr.ToString(); } } return string.Empty; } } public void Start(string host_ip) { this.host_ip = host_ip; img_sever = new ImageServer(MyIP, 20004); img_sever.RecvedImage += new RecvImageEventHandler(img_sever_RecvedImage); SetupClient.Setup(host_ip, 20002); } void img_sever_RecvedImage(object sender, RecvImageEventArgs e) { if (RecvedImage != null) { RecvedImage(this, e); } } public void StartEventClient() { sce = new SendEventClient(host_ip, 20010); } public void Stop() { if (img_sever != null) { img_sever.Close(); img_sever = null; } } } }
//NetworkInfo.cs using System.Net; using System.Net.Sockets; namespace 원격제어기 { /// /// 네트워크 정보 클래스 - 정적 클래스 /// public static class NetworkInfo { /// /// 이미지 서버 포트 - 가져오기 /// public static short ImgPort { get { return 20004; } } /// /// 원격 제어 요청 포트 - 가져오기 /// public static short SetupPort { get { return 20002; } } /// /// 이벤트 서버 포트 /// public static short EventPort { get { return 20010; } } /// /// 디폴트 IP 주소 문자열 - 가져오기 /// public static string DefaultIP { get { //호스트 이름 구하기 string host_name = Dns.GetHostName(); //호스트 엔트리 구하기 IPHostEntry host_entry = Dns.GetHostEntry(host_name); //호스트 주소 목록 반복 foreach (IPAddress ipaddr in host_entry.AddressList) { //주소 체계가 InterNetwork일 때 if (ipaddr.AddressFamily == AddressFamily.InterNetwork) { return ipaddr.ToString();//IP 주소 문자열 반환 } } return string.Empty;//빈 문자열 반환 } } } }