1. 유튜브 동영상 강의
6. 원격 제어 요청 수신 서버
원격 제어 요청을 수신하는 SetupServer 클래스도 정적 클래스로 정의합시다.
public static class SetupServer
{
서버 측은 연결 요청을 수신하기 위한 Listening 소켓을 생성하는 부분과 연결 요청을 대기하고 수용하는 부분으로 나눌 수 있습니다. 특히 연결 요청을 대기하고 수용하는 부분은 무한 반복할 것으로 블로킹을 막기 위해 여기에서는 스레드를 사용할게요.
Listening 소켓을 멤버로 선언합시다.
static Socket lis_sock; //연결 요청 수신 Listening 소켓
무한 대기하는 부분의 스레드를 멤버로 선언합시다.
static Thread accept_thread = null; //연결 요청 허용 스레드
연결 요청이 왔을 때 이벤트 처리를 위해 RecvRCInfoEventHandler 형식의 이벤트를 멤버로 선언하세요.
//연결 요청 수신 이벤트 핸들러
static public event RecvRCInfoEventHandler RecvedRCInfo = null;
Setup서버를 시작하는 메서드에서도 IP 주소와 포트 번호를 입력 인자로 받습니다.
static public void Start(string ip, int port)
{
먼저 TCP 소켓을 생성합니다.
//로컬 호스트의 IPEndPoint 개체 생성
IPAddress ipaddr = IPAddress.Parse(ip);
IPEndPoint ep = new IPEndPoint(ipaddr, port);
//연결 요청 수신 Listening 소켓 생성
lis_sock = new Socket(AddressFamily.InterNetwork, //네트워크 주소 체계
SocketType.Stream,//전송 방식
ProtocolType.Tcp);//프로토콜
소켓과 IPEndPoint를 결합하고 Back 로그 큐 크기를 설정하세요.
lis_sock.Bind(ep);//소켓과 IPEndPoint 결합
lis_sock.Listen(1); //Back 로그 큐 크기 설정
연결 요청을 대기하고 수용하는 스레드를 생성하고 시작합니다.
ThreadStart ts = new ThreadStart(AcceptLoop); //연결 요청 허용 쓰레드 진입점 개체 생성
accept_thread = new Thread(ts); //연결 요청 허용 쓰레드 생성
accept_thread.Start(); //연결 요청 허용 쓰레드 시작
}
다음은 연결 요청을 대기하는 메서드를 작성합시다.
static void AcceptLoop()
{
try
{
연결 요청을 대기하고 수용하는 부분 Listen 소켓의 Accept 메서드를 호출는 것을 반복합니다.
while (true)
{
Socket do_sock = lis_sock.Accept();//연결 수락
if (RecvedRCInfo != null) //연결 요청 수신 이벤트 핸들러가 있을 때
{
연결 요청을 수신하는 이벤트 핸들러가 있다면 이벤트 인자를 생성하여 이벤트를 발생합니다.
RecvRCInfoEventArgs e = new RecvRCInfoEventArgs(do_sock.RemoteEndPoint);
RecvedRCInfo(null, e); //이벤트 발생
}
연결 요청을 수신하였는지 알 수 있게 이벤트를 발생했으니 do_sock은 닫습니다.
do_sock.Close();//소켓 닫기
}
}
catch
{
Close();
}
}
SetupServer를 종료할 수 있게 Close 메서드를 정의합시다.
public static void Close()
{
소켓을 해제화 작업을 수행합니다.
if (lis_sock != null)
{
lis_sock.Close();
lis_sock = null;
}
}
}
다음은 이번 실습에서 작성한 소스 코드입니다.
//SetupServer.cs
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace 원격제어기
{
/// <summary>
/// 연결 요청 수신 서버 클래스 - 정적 클래스
/// </summary>
public static class SetupServer
{
static Socket lis_sock; //연결 요청 수신 Listening 소켓
static Thread accept_thread = null; //연결 요청 허용 스레드
/// <summary>
/// 연결 요청 수신 이벤트 핸들러
/// </summary>
static public event RecvRCInfoEventHandler RecvedRCInfo = null;
/// <summary>
/// 연결 요청 수신 서버 시작 메서드
/// </summary>
/// <param name="ip">서버의 IP주소</param>
/// <param name="port">포트</param>
static public void Start(string ip, int port)
{
//로컬 호스트의 IPEndPoint 개체 생성
IPAddress ipaddr = IPAddress.Parse(ip);
IPEndPoint ep = new IPEndPoint(ipaddr, port);
//연결 요청 수신 Listening 소켓 생성
lis_sock = new Socket(AddressFamily.InterNetwork, //네트워크 주소 체계
SocketType.Stream,//전송 방식
ProtocolType.Tcp);//프로토콜
lis_sock.Bind(ep);//소켓과 IPEndPoint 결합
lis_sock.Listen(1); //Back 로그 큐 크기 설정
//연결 요청 허용 쓰레드 진입점 개체 생성
ThreadStart ts = new ThreadStart(AcceptLoop);
accept_thread = new Thread(ts); //연결 요청 허용 쓰레드 생성
accept_thread.Start(); //연결 요청 허용 쓰레드 시작
}
static void AcceptLoop()
{
try
{
while (true)
{
Socket do_sock = lis_sock.Accept();//연결 수락
if (RecvedRCInfo != null) //연결 요청 수신 이벤트 핸들러가 있을 때
{
RecvRCInfoEventArgs e = new RecvRCInfoEventArgs(
do_sock.RemoteEndPoint);//이벤트 인자 생성
RecvedRCInfo(null, e); //이벤트 발생
}
do_sock.Close();//소켓 닫기
}
}
catch
{
Close();
}
}
/// <summary>
/// 연결 요청 수신 서버 닫기
/// </summary>
public static void Close()
{
if (lis_sock != null)
{
lis_sock.Close();
lis_sock = null;
}
}
}
}
이 책에서는 비동기적인 요소를 스레드로 작성하고 있습니다. 소켓의 비동기 메서드를 이용하여 프로그래밍하면 보다 나은 형태로 작성할 수 있습니다. 그 부분은 여러분의 몫으로 남길게요.
*Accept 부분을 BeginAccept 메서드 호출로 비동기 처리하는 코드입니다. 동영상 강의를 참고하세요. 동영상 강의에서는 RecvRCInfoEventArgs 부분을 라이브러리로 제작하였습니다.
그리고 해당 형식의 namespace를 RCEventArgsLib로 정했습니다.
첫 using 문은 이러한 이유 때문입니다.*
using RCEventArgsLib;
using System;
using System.Net;
using System.Net.Sockets;
namespace 원격제어기
{
public static class SetupServer
{
static Socket lis_sock;
static public event RecvRCInfoEventHandler RecvedRCInfoEventHandler = null;
static string ip;
static int port;
public static void Start(string ip,int port)
{
SetupServer.ip = ip;
SetupServer.port = port;
SocketBooting();
}
private static void SocketBooting()
{
IPAddress ipaddr = IPAddress.Parse(ip);
IPEndPoint ep = new IPEndPoint(ipaddr, port);
lis_sock = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
lis_sock.Bind(ep);
lis_sock.Listen(1);
lis_sock.BeginAccept(DoAccept, null);
}
static void DoAccept(IAsyncResult result)
{
if(lis_sock == null)
{
return;
}
try
{
Socket sock = lis_sock.EndAccept(result);
DoIt(sock);
lis_sock.BeginAccept(DoAccept, null);
}
catch
{
Close();
}
}
static void DoIt(Socket dosock)
{
if(RecvedRCInfoEventHandler != null)
{
RecvRCInfoEventArgs e = new RecvRCInfoEventArgs(dosock.RemoteEndPoint);
RecvedRCInfoEventHandler(null, e);
}
dosock.Close();
}
public static void Close()
{
if(lis_sock != null)
{
lis_sock.Close();
lis_sock = null;
}
}
}
}
'프로젝트 > C# 원격제어 프로그램' 카테고리의 다른 글
[C#] 원격 제어 프로그램 2. 원격 제어에서 작성할 형식 소개 (1) | 2024.01.08 |
---|---|
[C#] 원격 제어 프로그램 3. 프로젝트 생성 및 MainForm 자식 컨트롤 배치 (1) | 2024.01.08 |
[C#] 원격 제어 프로그램 4. 원격 제어 요청 클라이언트 (0) | 2024.01.08 |
[C#] 원격 제어 프로그램 5. 원격 제어 요청 수신 이벤트 (0) | 2024.01.08 |
[C#] 원격 제어 프로그램 7. 원격 제어 – 화면 전송 (0) | 2024.01.08 |
[C#] 원격 제어 프로그램 8. 원격 제어 – 화면 수신 이벤트 (1) | 2024.01.08 |
[C#] 원격 제어 프로그램 9. 원격 제어 – 화면 수신 서버 (0) | 2024.01.08 |
[C#] 원격 제어 프로그램 11. 원격 제어 이벤트 수신 버퍼 분석 (0) | 2024.01.08 |