일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 표준 입출력
- c#
- 캡슐화
- C++
- 언제나휴일
- 소스 코드
- 추천
- 산책하기 좋은 곳
- 졸업 작품
- 유튜브 동영상 강의
- 졸업 작품 소재
- 네트워크 프로그래밍
- 강의
- 언제나 휴일
- 실습으로 다지는 c#
- 충남 천안
- 동영상
- 실습
- 동영상 강의
- 프로젝트
- 소켓 통신
- 클래스 다이어그램
- 원격 제어 프로그램
- 안드로이드 앱 개발
- Windows Forms
- 무료 동영상 강의
- 파이썬
- 알고리즘
- 표준 라이브러리 함수
- c언어
- Today
- Total
프로그래밍 언어 및 기술 [언제나휴일]
[C#] 원격 제어 프로그램 6. 원격 제어 요청 수신 서버 본문
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#] 원격 제어 프로그램 10. 원격 제어 이벤트 전송 클라이언트 (1) | 2024.01.08 |