서론
이 글에서 다른 PC에 접속하기 위해서 가장 중요한 TCP/IP 통신을 이용한 서버와 클라이언트의 비동기 소켓 구조로 만든 소스를 정리 할려고한다. 통신간 기능 로직은 아직 작성하지 않았고 Connect - Accept 과정을 작성한 글이며, 자세한 기능 로직은 추 후 완성 코드를 보면 좋을 것 같다. 개비할수록 소스의 변형이 일어날 수 있지만 처음 설계는 멀티스레드 구조가 아닌 비동기로 작성했다.
(쓰레드를 안돌리고 비동기로 작성한 이유는 정리하여 이 후에 작성해보겠다.)
코드 (클라이언트)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace 원격제어_프로그램
{
public static class SetupClient
{
public static event EventHandler ConnectedEventHandler = null;
public static event EventHandler ConnectFiledEventHandler = null;
static Socket sock = null;
public static void Setup(string ip, int port)
{
IPAddress ipaddr = IPAddress.Parse(ip);
IPEndPoint ep = new IPEndPoint(ipaddr, port);
sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//비동기 Connect
sock.BeginConnect(ep, DoConnect, null);
}
/// <summary>
/// 비동기 Connect 함수
/// </summary>
/// <param name="result"></param>
static void DoConnect(IAsyncResult result)
{
IAsyncResult ar = result;
try
{
sock.EndConnect(result);
//비동기니까 값이 없을 수도 있으니 이벤트 핸들러 null 체크
if(ConnectedEventHandler != null)
{
ConnectedEventHandler(null, new EventArgs());
}
}
catch (SocketException sock_ex)
{
if(ConnectFiledEventHandler != null)
{
ConnectFiledEventHandler(null, new EventArgs());
}
}
sock.Close();
}
}
}
코드 (서버)
using MyDemoLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace 원격제어_프로그램
{
class SetupServer
{
static Socket lis_sock;
public static event RecvRCInfoEventHandler RecvedRCInfoEventHandler = null;
static string ip = string.Empty;
static int port = -1;
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);
}
private 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 (Exception ex)
{
Close();
}
}
private 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;
}
}
}
}
현재 기본 통신 껍데기만 만들어져있는 상태이며 상세 로직은 추 후 추가 예정이다.
Server는 Mainform Load시 Start함수로 비동기 방식으로 Listen 대기 예정.
Client는 비동기 함수인 BeginAccept를 이용하여 서버에게 Connect함.
반응형
'Project History > 원격 제어 프로그램 만들기' 카테고리의 다른 글
[C# 원격 제어 프로그램 만들기 #04] 원격 프로그램 서버 / 클라이언트 구현 최종 (0) | 2022.02.09 |
---|---|
[C# 원격 제어 프로그램 만들기 #03] Win API (user32.dll)을 이용한 윈도우 이벤트 구현 (DllImport / Win32 API / keybd_event 등) (0) | 2022.01.09 |
[C# 원격 제어 프로그램 만들기 #02] TCP/IP를 이용한 이미지 전송 프로그램 만들기 (0) | 2022.01.04 |
[C# 원격 제어 프로그램 만들기 #00] 클래스 / 역할 정리 (0) | 2021.12.26 |
댓글