원격 제어 프로그램 14. 원격 제어 컨트롤러

이제 원격 제어 컨트롤러를 만들어 봅시다. 먼저 공통으로 사용할 부분을 작성할게요.

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;//빈 문자열 반환
            }
        }
    }
}