using System; using System.Net; using System.Net.Sockets; using System.Threading; namespace Sodao.FastSocket.Server { /// /// socket listener /// public sealed class SocketListener : ISocketListener { #region Private Members private readonly SocketBase.IHost _host = null; private const int BACKLOG = 500; private Socket _socket = null; private readonly SocketAsyncEventArgs _ae = null; #endregion #region Constructors /// /// new /// /// /// /// endPoint is null /// host is null public SocketListener(IPEndPoint endPoint, SocketBase.IHost host) { if (endPoint == null) throw new ArgumentNullException("endPoint"); if (host == null) throw new ArgumentNullException("host"); this.EndPoint = endPoint; this._host = host; this._ae = new SocketAsyncEventArgs(); this._ae.Completed += this.AcceptCompleted; } #endregion #region ISocketListener Members /// /// socket accepted event /// public event Action Accepted; /// /// get listener endPoint /// public EndPoint EndPoint { get; private set; } /// /// start /// public void Start() { if (this._socket == null) { this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this._socket.Bind(this.EndPoint); this._socket.Listen(BACKLOG); this.AcceptAsync(this._socket); } } /// /// stop /// public void Stop() { if (this._socket != null) { this._socket.Close(); this._socket = null; } } #endregion #region Private Methods /// /// accept socket. /// /// private void AcceptAsync(Socket socket) { if (socket == null) return; bool completed = true; try { completed = this._socket.AcceptAsync(this._ae); } catch (Exception ex) { SocketBase.Log.Trace.Error(ex.Message, ex); } if (!completed) ThreadPool.QueueUserWorkItem(_ => this.AcceptCompleted(this, this._ae)); } /// /// async accept socket completed handle. /// /// /// private void AcceptCompleted(object sender, SocketAsyncEventArgs e) { Socket accepted = null; if (e.SocketError == SocketError.Success) accepted = e.AcceptSocket; e.AcceptSocket = null; if (accepted != null) this.Accepted(this, this._host.NewConnection(accepted)); //continue to accept! this.AcceptAsync(this._socket); } #endregion } }