*동영상 강의에서는 Connect 부분을 비동기로 처리하는 BeginConnect를 호출합니다. 그리고 연결 요청 성공과 실패를 처리할 수 있게 이벤트를 추가 정의하였습니다. *
원격 제어를 요청하는 SetupClient 클래스를 구현합시다.
SetupClient는 단순히 상대에게 누가 요청하는지 알려주는 역할만 수행할 거예요. 값을 유지할 필요도 없고 개체를 만들 필요도 없는 클래스이므로 정적 클래스로 정의하세요.
public static class SetupClient {
Setup 클라이언트에서는 원격 제어하고자 하는 상대 IP와 포트 정보를 입력 인자로 받습니다.
public static void Setup(string ip, int port) {
상대 IP 주소를 입력 인자로 IPEndPoint 개체를 생성하세요.
IPAddress ipaddr = IPAddress.Parse(ip); //상대 IP 주소 개체를 생성 IPEndPoint ep = new IPEndPoint(ipaddr, port); //IP 단말 주소(IP주소 + 포트번호) 개체 생성
TCP 방식의 소켓을 생성합니다.
//TCP 소켓 생성(네트워크 주소 체계, 전송 방식, 프로토콜) Socket sock = new Socket(AddressFamily.InterNetwork, //네트워크 주소 체계 SocketType.Stream, //전송 방식 ProtocolType.Tcp);//프로토콜
연결한 후에 바로 닫습니다. 원격 제어를 수용할 지 여부를 판단하는 곳에 원격 제어 요청이 있다는 것을 알려주는 목적 뿐이어서 전달할 정보는 없습니다.
sock.Connect(ep);//연결 요청 sock.Close();//소켓 닫기 } }
이처럼 작성하여 컴파일하면 “형식 또는 네임 스페이스 이름을 찾을 수 없습니다.”와 같은 오류 메시지가 뜰 거예요. IPAddress와 IPEndPoint, Socket 등을 사용하기 위해 필요한 네임 스페이스를 소스 코드 맨 위에 추가하세요.
using System.Net; using System.Net.Sockets;
Microsoft Visual Studio에서 프로그래밍할 때 어떠한 형식이 어느 namespace에 있는지 모르더라도 작성한 형식 이름에 커서를 위치한 상태에서 Ctrl키와 .(DOT)을 누르면 아래처럼 인텔리센스가 동작하여 쉽게 using 문을 추가할 수 있습니다. (개발 도구 버전에 따라 다를 수 있습니다.)
다음은 이번 실습에서 작성한 소스 코드입니다.
//SetupClient.cs using System.Net; using System.Net.Sockets; namespace 원격제어기 { /// <summary> /// 원격 제어 요청 클라이언트 - 정적 클래스 /// </summary> public static class SetupClient { /// <summary> /// 원격 제어 요청 메서드 /// </summary> /// <param name="ip">상대 IP 주소</param> /// <param name="port">상대 포트 번호</param> public static void Setup(string ip, int port) { IPAddress ipaddr = IPAddress.Parse(ip); //상대 IP 주소 개체를 생성 IPEndPoint ep = new IPEndPoint(ipaddr, port); //IP 단말 주소(IP주소 + 포트번호) 개체 생성 //TCP 소켓 생성(네트워크 주소 체계, 전송 방식, 프로토콜) Socket sock = new Socket(AddressFamily.InterNetwork, //네트워크 주소 체계 SocketType.Stream, //전송 방식 ProtocolType.Tcp);//프로토콜 sock.Connect(ep);//연결 요청 sock.Close();//소켓 닫기 } } }
다음은 연결 요청 부분을 비동기로 처리하여 연결 요청 과정에 Blocking 현상이 발생하지 않도록 품질 수준을 높인 코드입니다. 동영상 강의를 참고하세요.
using System; using System.Net; using System.Net.Sockets; namespace 원격제어기 { /// /// 원격 제어 요청 클라이언트 - 정적 클래스 /// public static class SetupClient { public static event EventHandler ConnectedEventHandler = null; public static event EventHandler ConnectFailedEventHandler = null; static Socket sock; /// /// 원격 제어 요청 메서드 /// ///상대 IP 주소 ///상대 포트 번호 public static void Setup(string ip, int port) { IPAddress ipaddr = IPAddress.Parse(ip); //상대 IP 주소 개체를 생성 IPEndPoint ep = new IPEndPoint(ipaddr, port); //IP 단말 주소(IP주소 + 포트번호) 개체 생성 //TCP 소켓 생성(네트워크 주소 체계, 전송 방식, 프로토콜) sock = new Socket(AddressFamily.InterNetwork, //네트워크 주소 체계 SocketType.Stream, //전송 방식 ProtocolType.Tcp);//프로토콜 //sock.Connect(ip, port); sock.BeginConnect(ep, DoConnect, sock); } static void DoConnect(IAsyncResult result) { try { sock.EndConnect(result); if(ConnectedEventHandler != null) { ConnectedEventHandler(null, new EventArgs());//연결 성공 } } catch { if(ConnectFailedEventHandler != null) { ConnectFailedEventHandler(null, new EventArgs());//연결 실패 } } sock.Close(); } } }