비동기 소켓 클라이언트 클래스 만들어 봄.
.NET Compact Framework 2.0 용
사용법)
private void SockDataReceived(Socket sock, byte[] data, int readBytes)
{
// 수신된 메시지 처리
}
...
AsyncSocketClient asc = new AsyncSocketClient();
asc.StartSend("192.168.1.100", 7788, "hello world\r\n", this.SockDataReceived, true);
...
현재 ASCII 엔코딩만 지원함.ㅋㅋㅋ
public class AsyncSocketClient
{
private byte[] txMessage;
private Socket client;
private Boolean doEndConnection;
private DataReceivedCallback dataReceivedCallback;
public delegate void DataReceivedCallback(Socket sock, byte[] data, int bytesRead);
private class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 256;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public AsyncSocketClient()
{
this.txMessage = null;
this.client = null;
this.doEndConnection = false;
this.dataReceivedCallback = null;
}
public void SetDataReceivedCallback(DataReceivedCallback callback)
{
this.dataReceivedCallback = new DataReceivedCallback(callback);
}
private void ConnectCallback(IAsyncResult ar)
{
Socket s = (Socket)ar.AsyncState;
try
{
s.EndConnect(ar);
// 연결되었으면
if (s.Connected)
{
// 전송할 메시지가 있으면
if (this.txMessage != null)
{
// 전송한다.
s.Send(this.txMessage);
}
if (this.dataReceivedCallback != null)
{
// 수신시작
StateObject state = new StateObject();
state.workSocket = s;
s.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(this.ReceiveCallback), state);
}
}
else
{
// 소켓 리소스 해제
s.Shutdown(SocketShutdown.Both);
s.Close();
}
}
catch (Exception) { }
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// 응용의 콜백 호출
if (this.dataReceivedCallback != null)
{
byte[] recvData = Encoding.ASCII.GetBytes(state.sb.ToString());
this.dataReceivedCallback(client, recvData, recvData.Length);
}
if (this.doEndConnection)
{
client.Shutdown(SocketShutdown.Both);
client.Close();
}
else
{
// Get the rest of the data.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(this.ReceiveCallback), state);
}
}
else
{
if (client.Connected)
{
client.Shutdown(SocketShutdown.Both);
client.Close();
}
}
}
catch (Exception e)
{
e.ToString();
}
}
/// <summary>
/// 현재 연결되어 있는 상태에서 전송하고 싶은 때 사용하라
/// </summary>
/// <param name="msg">전송하고싶은 문자열</param>
/// <returns></returns>
public Boolean Send(String msg)
{
if (this.client == null) return false;
if (this.client.Connected == false) return false;
return this.client.Send(Encoding.ASCII.GetBytes(msg)) > 0;
}
/// <summary>
/// 최초 전송시작시 사용하라
/// </summary>
/// <param name="serverIP">대상 IP</param>
/// <param name="port">대상 포트</param>
/// <param name="msg">전송할 메시지</param>
/// <param name="rxCallback">데이터 수신 콜백</param>
/// <param name="doEndConnection">데이터 수신후 접속종료 여부</param>
/// <returns></returns>
public Boolean StartSend(String serverIP, int port, String msg, DataReceivedCallback rxCallback, Boolean doEndConnection)
{
// 이미 연결되어 있으면 소켓을 종료시킨다.
if (this.client != null && this.client.Connected)
{
this.client.Shutdown(SocketShutdown.Both);
this.client.Close();
}
this.client = null;
this.doEndConnection = doEndConnection;
this.SetDataReceivedCallback(rxCallback);
try
{
// 소켓 생성
IPAddress ipAddress = IPAddress.Parse(serverIP);
IPEndPoint ipEP = new IPEndPoint(ipAddress, port);
this.client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 전송할 데이터 지정
this.txMessage = System.Text.Encoding.ASCII.GetBytes(msg);
// 연결 시작
IAsyncResult asyncResult = client.BeginConnect(ipEP, new AsyncCallback(this.ConnectCallback), this.client);
}
catch (Exception)
{
if (this.client != null)
{
if (this.client.Connected)
{
this.client.Shutdown(SocketShutdown.Both);
this.client.Close();
}
}
return false;
}
return true;
}
}