using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using SuperSocket.SocketBase.Logging;
namespace SuperSocket.SocketEngine
{
///
/// Tcp socket listener in async mode
///
class TcpAsyncSocketListener : SocketListenerBase
{
private int m_ListenBackLog;
private Socket m_ListenSocket;
private SocketAsyncEventArgs m_AcceptSAE;
public TcpAsyncSocketListener(ListenerInfo info)
: base(info)
{
m_ListenBackLog = info.BackLog;
}
///
/// Starts to listen
///
/// The server config.
///
public override bool Start(IServerConfig config)
{
m_ListenSocket = new Socket(this.Info.EndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
m_ListenSocket.Bind(this.Info.EndPoint);
m_ListenSocket.Listen(m_ListenBackLog);
m_ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
m_ListenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs();
m_AcceptSAE = acceptEventArg;
acceptEventArg.Completed += new EventHandler(acceptEventArg_Completed);
if (!m_ListenSocket.AcceptAsync(acceptEventArg))
ProcessAccept(acceptEventArg);
return true;
}
catch (Exception e)
{
OnError(e);
return false;
}
}
void acceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
{
ProcessAccept(e);
}
void ProcessAccept(SocketAsyncEventArgs e)
{
Socket socket = null;
if (e.SocketError != SocketError.Success)
{
var errorCode = (int)e.SocketError;
//The listen socket was closed
if (errorCode == 995 || errorCode == 10004 || errorCode == 10038)
return;
OnError(new SocketException(errorCode));
}
else
{
socket = e.AcceptSocket;
}
e.AcceptSocket = null;
bool willRaiseEvent = false;
try
{
willRaiseEvent = m_ListenSocket.AcceptAsync(e);
}
catch (ObjectDisposedException)
{
//The listener was stopped
//Do nothing
//make sure ProcessAccept won't be executed in this thread
willRaiseEvent = true;
}
catch (NullReferenceException)
{
//The listener was stopped
//Do nothing
//make sure ProcessAccept won't be executed in this thread
willRaiseEvent = true;
}
catch (Exception exc)
{
OnError(exc);
//make sure ProcessAccept won't be executed in this thread
willRaiseEvent = true;
}
if (socket != null)
OnNewClientAccepted(socket, null);
if (!willRaiseEvent)
ProcessAccept(e);
}
public override void Stop()
{
if (m_ListenSocket == null)
return;
lock (this)
{
if (m_ListenSocket == null)
return;
m_AcceptSAE.Completed -= new EventHandler(acceptEventArg_Completed);
m_AcceptSAE.Dispose();
m_AcceptSAE = null;
try
{
m_ListenSocket.Close();
}
finally
{
m_ListenSocket = null;
}
}
OnStopped();
}
}
}