비동기 소켓 클라이언트 클래스 만들어 봄.
.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; } }