C# TCP/IP 를 이용한 Client 클래스
Software/C#2023. 2. 13. 10:53
반응형
지난 글에서 멀티 Thread 를 이용한 서버를 구현했고 이번에는 Client 모듈을 클래스로 구현해 보았습니다.
서버와의 연결 및 해제에 대한 이벤트와 데이타 수신에 대한 이벤트를 발생하도록 구현되어 있습니다. Client 객체를 생성한 후에 데이타 수신 이벤트를 구현하여 수신된 데이타를 원하는 목적으로 사용할 수 있습니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Client
{
public class ServerEventArgs : EventArgs
{
public string text { get; } // 파라메터로 넘겨 줄 데이타
public ServerEventArgs(string text) // 생성자에서 변경된 Text 정보를 넘겨받는다.
{
this.text = text;
}
}
internal class Client
{
public delegate void ClientEventHandler(object sender, ServerEventArgs e);
public delegate void ServerDisConnectHandler(object sender, EventArgs e);
private NetworkStream? stream = null ;
private StreamReader? reader = null;
private StreamWriter? writer = null;
private readonly TcpClient? client = null;
public string ServerIP { set; get; } = "127.0.0.1";
public int ServerPort { set; get; }
private bool _connected = false;
public event ClientEventHandler? OnDataReceived = null;
public event ClientEventHandler? OnServerConnected = null;
public event ServerDisConnectHandler? OnServerDisconnected = null;
//--------------------------------------------------------------------------------------------------------------
public bool Connected
{
get { return _connected; }
}
//--------------------------------------------------------------------------------------------------------------
public Client()
{
var clientIP = GetLocalIP();
var port = 10001;
if (clientIP != null)
{
IPEndPoint clientAddress = new IPEndPoint(IPAddress.Parse(clientIP.ToString()), port);
client = new TcpClient(clientAddress);
}
}
//--------------------------------------------------------------------------------------------------------------
public Client(string serverIP, int serverPort)
{
ServerIP = serverIP;
ServerPort = serverPort;
var clientIP = GetLocalIP();
var port = 10001;
if (clientIP != null)
{
IPEndPoint clientAddress = new IPEndPoint(IPAddress.Parse(clientIP.ToString()), port);
client = new TcpClient(clientAddress);
}
}
//--------------------------------------------------------------------------------------------------------------
private static string GetLocalIP()
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
string ip = string.Empty;
foreach (var address in host.AddressList)
{
if (address.AddressFamily == AddressFamily.InterNetwork)
{
ip = address.ToString();
break;
}
}
return ip;
}
//--------------------------------------------------------------------------------------------------------
public void Connect()
{
IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse(ServerIP), ServerPort);
client?.Connect(serverAddress);
_connected = (bool)client?.Connected!;
if(_connected)
{
stream = client.GetStream();
reader = new StreamReader(stream, Encoding.GetEncoding("utf-8"));
writer = new StreamWriter(stream, Encoding.GetEncoding("utf-8")) { AutoFlush = true };
if(OnServerConnected is not null)
{
OnServerConnected(this, new ServerEventArgs(serverAddress.ToString())); // 서버 연결에 대한 이벤트 함수 실행
}
Thread receive_thread = new Thread(ReceiveMessage);
receive_thread.Start();
}
}
//--------------------------------------------------------------------------------------------------------------
public void Disconnect()
{
if(_connected)
{
_connected = false;
reader?.Close();
writer?.Close();
stream?.Close();
client?.Close();
}
}
//--------------------------------------------------------------------------------------------------------------
public void SendMessage(string message)
{
writer?.WriteLine(message);
}
//--------------------------------------------------------------------------------------------------------------
private void ReceiveMessage()
{
string? message;
while(_connected)
{
try
{
message = reader?.ReadLine();
if (message == null) break;
if (OnDataReceived is not null)
{
OnDataReceived(this, new ServerEventArgs(message)); // 데이타 수신에 대한 이벤트 함수 실행
}
}
catch (Exception ex)
{
if (OnServerDisconnected is not null)
{
OnServerDisconnected(this, new EventArgs());
}
break;
}
}
}
//--------------------------------------------------------------------------------------------------------------
}
}
사용 방법은 아래와 같습니다. 아래 코드에서 서버와의 연결 / 해제에 대한 이벤트는 없지만 필요하면 client 클래스 코드를 보시고 추가 하시면 됩니다.
public partial class Form1 : Form
{
Client client = new Client("192.168.0.12", 5555);
public Form1()
{
InitializeComponent();
client.OnDataReceived += DataReceived;
}
private void button1_Click(object sender, EventArgs e)
{
client.Connect();
}
private void button2_Click(object sender, EventArgs e)
{
client.SendMessage(textBox1.Text);
}
private void button3_Click(object sender, EventArgs e)
{
client.Disconnect();
}
private void DataReceived(object sender, ServerEventArgs e)
{
// client 클래스에서 데이타 수신부가 thread로 구현되어 있기 때문에
메인 화면의 TextBox 에 수신된 데이타를 쓸경우 아래와 같이 Invoke를
사용했습니다.
textBox2.Invoke(() => { textBox2.Text = e.text; });
}
}
반응형
'Software > C#' 카테고리의 다른 글
ScottPlot (Growing Data - #2) (2) | 2023.02.16 |
---|---|
ScottPlot (Growing Data - #1) (0) | 2023.02.16 |
C# Multi Thread를 이용한 다중 Client 접속 Server (1) | 2023.02.11 |
C# 델리게이트를 이용한 이벤트 생성 (Part-3) (0) | 2023.02.06 |
C# 델리게이트를 이용한 이벤트 생성 (Part-2) (0) | 2023.02.05 |
댓글()