반응형
비동기 재접속이 가능한 TCPCLIENT
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
namespace TCPClient01
{
public partial class Form1 : Form
{
TcpClient mTcpClient;
byte[] mRx;
//서버에 연결되어 있는지 확인
bool bConnected = false;
private bool Connected { get => mTcpClient == null ? false : mTcpClient.Connected && bConnected; }
//접속시 사용한 IP PORT
int iPort;
IPAddress iPAddress;
//재접속 타이머
System.Timers.Timer timer1 = new System.Timers.Timer();
public Form1()
{
InitializeComponent();
timer1.Interval = 1000;
timer1.Elapsed += new System.Timers.ElapsedEventHandler(timer1_Elasped);
}
private void btnConnect_Click(object sender, EventArgs e)
{
if (mTcpClient != null && Connected /*mTcpClient.Connected*/) return ; //연결이 되어 있는데 또 연결 방지용, 서버쪽에 연결된 노드가 늘어남
IPAddress ipa;
int nPort;
try
{
if (string.IsNullOrEmpty(tbServerIP.Text) || string.IsNullOrEmpty(tbServerPort.Text))
return;
if (!IPAddress.TryParse(tbServerIP.Text, out ipa))
{
MessageBox.Show("Please supply an IP Address.");
return;
}
if (!int.TryParse(tbServerPort.Text, out nPort))
{
nPort = 23000;
}
mTcpClient = new TcpClient();
mTcpClient.BeginConnect(ipa, nPort, onCompleteConnect, mTcpClient);
iPAddress = ipa ;
iPort = nPort;
bConnecting = true ;
timer1.Start();
}
catch (Exception exc)
{
bConnected = false;
MessageBox.Show(exc.Message);
}
}
bool bFirstConnect = false;
bool bConnecting = false ;
void onCompleteConnect(IAsyncResult iar)
{
TcpClient tcpc;
try
{
//iar.AsyncWaitHandle.WaitOne(1000, false);
tcpc = (TcpClient)iar.AsyncState;
tcpc.EndConnect(iar);
mRx = new byte[512];
tcpc.GetStream().BeginRead(mRx, 0, mRx.Length, onCompleteReadFromServerStream, tcpc);
bConnected = true; //연결 성공
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
bConnected = false; //연결 실패
}
bConnecting = false;
}
void onCompleteReadFromServerStream(IAsyncResult iar)
{
TcpClient tcpc;
int nCountBytesReceivedFromServer;
string strReceived;
try
{
tcpc = (TcpClient)iar.AsyncState;
nCountBytesReceivedFromServer = tcpc.GetStream().EndRead(iar);
if (nCountBytesReceivedFromServer == 0)
{
MessageBox.Show("Connection broken.");
return;
}
strReceived = Encoding.ASCII.GetString(mRx, 0, nCountBytesReceivedFromServer);
string s1 = Encoding.ASCII.GetString(mRx, 0, nCountBytesReceivedFromServer-1);
if(mRx[nCountBytesReceivedFromServer-1] != '\n') return;
printLine(strReceived);
mRx = new byte[512];
tcpc.GetStream().BeginRead(mRx, 0, mRx.Length, onCompleteReadFromServerStream, tcpc);
bConnected = true; //연결 성공
}
catch (Exception exc)
{
bConnected = false; //연결 실패
MessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public void printLine(string _strPrint)
{
tbConsole.Invoke(new Action<string>(doInvoke), _strPrint);
}
public void doInvoke(string _strPrint)
{
tbConsole.Text = _strPrint + Environment.NewLine + tbConsole.Text;
}
byte[] tx;
private void tbSend_Click(object sender, EventArgs e)
{
//byte[] tx;
if (string.IsNullOrEmpty(tbPayload.Text)) return;
try
{
if (!Connected) return;
tx = Encoding.ASCII.GetBytes(tbPayload.Text + "\r\n");
if (mTcpClient != null)
{
if (mTcpClient.Client.Connected)
{
mTcpClient.GetStream().BeginWrite(tx, 0, tx.Length, onCompleteWriteToServer, mTcpClient);
}
}
}
catch (Exception exc)
{
bConnected = false;
MessageBox.Show(exc.Message);
}
}
void onCompleteWriteToServer(IAsyncResult iar)
{
TcpClient tcpc;
try
{
tcpc = (TcpClient)iar.AsyncState;
tcpc.GetStream().EndWrite(iar);
//bCompleted = true;
}
catch (Exception exc)
{
//bCompleted = false;
MessageBox.Show(exc.Message);
}
}
private void timer1_Elasped(object sender, EventArgs e)
{
timer1.Enabled = false;
bConnected = mTcpClient.Connected;
if (!mTcpClient.Connected && !bConnecting)
{
bConnecting = true;
mTcpClient.Close();
mTcpClient = new TcpClient();
mTcpClient.BeginConnect(iPAddress, iPort, onCompleteConnect, mTcpClient);
}
timer1.Enabled = true;
}
}
}
테스트 예제
연결
서버 실행후에 Start Listening 클릭
클라이언트 실행후에 Connect 클릭
Write & Read
클라이언트측 Send 클릭 - 서버측 확인후 현재시간 전송
서버측 Clients에서 연결된 클라이언트 선택후 Send 클릭 - 클라이언트측 받은 메시지 표기
재접속하려면 한번 Send 필요.
관련 소스 첨부
반응형
'C#' 카테고리의 다른 글
C# 절대값 Math.Abs 메서드 (feat float) (0) | 2021.06.22 |
---|---|
C# 현재시간 가져오기, datetime format (밀리세컨드 포함) (0) | 2021.06.21 |
C# string to int 문자열을 정수로 변환 (TryParse, Parse, Convert.ToInt) (0) | 2021.06.16 |
C# 문자열(string) 자르기 (Substring, Split, IndexOf) (0) | 2021.06.16 |
C# sleep과 지연함수 (delay) (0) | 2021.06.16 |