class EasySocket { public delegate void ConnectEvent(object sender); public delegate void ShutdownEvent(object sender); public delegate void ClientConnectedEvent(Socket socketConnected, object sender); public delegate void DataReceivedEvent(String data, Socket fromSocket, object sender); public delegate void DataSendEvent(object sender); public enum FamilyType { Tcp, Udp } public class Server : IDisposable { public Server() { EndToken = "\0"; } public event ClientConnectedEvent OnClientConnected; public event DataReceivedEvent OnDataReceive; public event DataSendEvent OnDataSent; public event ShutdownEvent OnShutdown; public FamilyType SocketFamilyType { get; set; } public int Port { get; set; } public int MaxClient { get; set; } public bool Universal { get; set; } public String EndToken { get; set; } public bool Started { get; private set; } public List SocketsConnected { get { return this.m_Sockets; } } public void Start() { if (String.IsNullOrEmpty(SocketFamilyType.ToString()) || Port == 0) return; else // I liked this style { m_EndPoint = new IPEndPoint(Universal ? IPAddress.Any : IPAddress.Loopback, Port); switch (SocketFamilyType) { case FamilyType.Tcp: m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); break; case FamilyType.Udp: m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); break; } try { m_Socket.Bind(m_EndPoint); m_Socket.Listen(MaxClient); m_Socket.BeginAccept(CallBack_OnAccept, m_Socket); Started = true; } catch (SocketException ex) { throw new Exception(String.Format("Port {0} has already been occupied.", Port)); } } } public void Disconnnect(Socket trySocket) { if (trySocket != null) { try { trySocket.BeginDisconnect(true, CallBack_OnDisconnect, trySocket); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } } public void Send(Socket socket, String data) { data += EndToken; byte[] byteData = Encoding.ASCII.GetBytes(data); socket.BeginSend(byteData, 0, byteData.Length, 0, CallBack_OnSend, socket); } public void Broadcast(String data) { foreach (var m_Socket_field in m_Sockets) Send(m_Socket_field, data); } public void Shutdown() { m_Socket.Close(); if (this.OnShutdown != null) OnShutdown(this); this.Dispose(); } private void CallBack_OnAccept(IAsyncResult ar) { Socket socketAccepted = null; try { socketAccepted = m_Socket.EndAccept(ar); m_Sockets.Add(socketAccepted); m_SocketsBuffer.Add(socketAccepted, new StringBuilder()); if (OnClientConnected != null) OnClientConnected(socketAccepted, this); socketAccepted.BeginReceive(m_Data, 0, m_Data.Length, SocketFlags.None, CallBack_OnReceive, socketAccepted); m_Socket.BeginAccept(CallBack_OnAccept, m_Socket); } catch (SocketException ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); Disconnnect(socketAccepted); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } private void CallBack_OnReceive(IAsyncResult ar) { Socket socketAccepted = null; try { socketAccepted = ar.AsyncState as Socket; int read = socketAccepted.EndReceive(ar); var sb = new StringBuilder(); if (read > 0) { String strRead = Encoding.ASCII.GetString(m_Data, 0, read); char lastChar = strRead[strRead.Length - 1]; //Console.WriteLine("{0}", strRead); Console.WriteLine("{0}", m_SocketsBuffer[socketAccepted]); if (lastChar != '\r' ) { m_SocketsBuffer[socketAccepted].Append(strRead); socketAccepted.BeginReceive(m_Data, 0, m_Data.Length, SocketFlags.None, CallBack_OnReceive, socketAccepted); return; } sb.Append(m_SocketsBuffer[socketAccepted]); //socketAccepted.BeginReceive(m_Data, 0, m_Data.Length, SocketFlags.None, CallBack_OnReceive, socketAccepted); } if (sb.Length > 0) { string content = sb.ToString(); if (!String.IsNullOrEmpty(EndToken)) { int index = content.IndexOf(EndToken, StringComparison.Ordinal); if (index != -1) content = content.Substring(0, index); } if (OnDataReceive != null) OnDataReceive(content, socketAccepted, this); // Flush it m_SocketsBuffer[socketAccepted] = new StringBuilder(); } } catch (SocketException ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); Disconnnect(socketAccepted); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } private void CallBack_OnSend(IAsyncResult ar) { Socket socketAccepted = null; try { socketAccepted = ar.AsyncState as Socket; // Complete sending the data to the remote device. socketAccepted.EndSend(ar); if (this.OnDataSent != null) OnDataSent(this); } catch (SocketException ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); Disconnnect(socketAccepted); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } private void CallBack_OnDisconnect(IAsyncResult ar) { try { Socket socketTryDisconnect = ar.AsyncState as Socket; socketTryDisconnect.EndDisconnect(ar); m_SocketsBuffer.Remove(socketTryDisconnect); m_Sockets.Remove(socketTryDisconnect); } catch (SocketException ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } private readonly Dictionary m_SocketsBuffer = new Dictionary(); private List m_Sockets = new List(); private byte[] m_Data = new byte[65535]; private IPEndPoint m_EndPoint; private Socket m_Socket; public void Dispose() { m_Data = null; m_Socket = null; m_Sockets = null; m_EndPoint = null; GC.Collect(); GC.SuppressFinalize(this); } } public class Client : IDisposable { public event ConnectEvent OnConnected; public event DataReceivedEvent OnDataReceive; public event DataSendEvent OnDataSent; public event ShutdownEvent OnShutdown; public FamilyType SocketFamilyType { get; set; } public string Destination { get; set; } public int Port { get; set; } public String EndToken { get; set; } public bool Conntected { get { return m_Socket.Connected; } } public void Connect() { if (String.IsNullOrEmpty(SocketFamilyType.ToString()) || Port == 0) return; else // I liked this style { m_EndPoint = new IPEndPoint(Array.Find(Dns.GetHostAddresses(Destination), a => a.AddressFamily == AddressFamily.InterNetwork), Port); switch (SocketFamilyType) { case FamilyType.Tcp: m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); break; case FamilyType.Udp: m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); break; } m_Socket.BeginConnect(m_EndPoint, CallBack_OnConnected, m_Socket); } } public void Send(String data) { data += EndToken; // Convert the string data to byte data using ASCII encoding. byte[] byteData = Encoding.ASCII.GetBytes(data); m_Socket.BeginSend(byteData, 0, byteData.Length, 0, CallBack_OnSend, m_Socket); } public void Shutdown() { m_Socket.Shutdown(SocketShutdown.Receive); if (this.OnShutdown != null) OnShutdown(this); this.Dispose(); } private void CallBack_OnSend(IAsyncResult ar) { try { m_Socket.EndSend(ar); if (this.OnDataSent != null) OnDataSent(this); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } private void CallBack_OnConnected(IAsyncResult ar) { try { m_Socket.EndConnect(ar); if (OnConnected != null) OnConnected(this); m_Socket.BeginReceive(m_Data, 0, m_Data.Length, SocketFlags.None, CallBack_OnReceive, m_Socket); } catch (SocketException ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } private void CallBack_OnReceive(IAsyncResult ar) { try { Socket socketAccepted = ar.AsyncState as Socket; int read = socketAccepted.EndReceive(ar); var sb = new StringBuilder(); if (read > 0) { sb.Append(Encoding.ASCII.GetString(m_Data, 0, read)); socketAccepted.BeginReceive(m_Data, 0, m_Data.Length, SocketFlags.None, CallBack_OnReceive, socketAccepted); } if (sb.Length > 0) { string content = sb.ToString(); if (!String.IsNullOrEmpty(EndToken)) { int index = content.IndexOf(EndToken); if (index != -1) content = content.Substring(0, index); } if (OnDataReceive != null) OnDataReceive(content, socketAccepted, this); } } catch (SocketException ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } private IPEndPoint m_EndPoint; private byte[] m_Data = new byte[65535]; private Socket m_Socket; public void Dispose() { this.m_Data = null; this.m_Socket = null; this.m_EndPoint = null; GC.Collect(); GC.SuppressFinalize(this); } } }