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
}
}