diff --git a/Scripts/Misc/SocketOptions.cs b/Scripts/Misc/SocketOptions.cs index 85a717bbd..52f5bc2d7 100644 --- a/Scripts/Misc/SocketOptions.cs +++ b/Scripts/Misc/SocketOptions.cs @@ -12,14 +12,17 @@ namespace Server { private const bool NagleEnabled = false; // Should the Nagle algorithm be enabled? This may reduce performance private const int CoalesceBufferSize = 512; // MSS that the core will use when buffering packets + private const int PooledSockets = 32; // The number of sockets to initially pool. Ideal value is expected client count. private static int[] m_AdditionalPorts = new int[0]; //private static int[] m_AdditionalPorts = new int[]{ 2594 }; public static void Initialize() { - EventSink.SocketConnect += new SocketConnectEventHandler( EventSink_SocketConnect ); SendQueue.CoalesceBufferSize = CoalesceBufferSize; + SocketPool.InitialCapacity = PooledSockets; + + EventSink.SocketConnect += new SocketConnectEventHandler( EventSink_SocketConnect ); if ( m_AdditionalPorts.Length > 0 ) EventSink.ServerStarted += new ServerStartedEventHandler( EventSink_ServerStarted ); diff --git a/Server/Main.cs b/Server/Main.cs index 256358231..0166804dd 100644 --- a/Server/Main.cs +++ b/Server/Main.cs @@ -245,6 +245,9 @@ namespace Server { } + if ( SocketPool.Created ) + SocketPool.Destroy(); + Console.WriteLine( "This exception is fatal, press return to exit" ); Console.ReadLine(); } @@ -327,6 +330,9 @@ namespace Server if( timerThread.ThreadState != System.Threading.ThreadState.Unstarted ) timerThread.Join(); + if( SocketPool.Created ) + SocketPool.Destroy(); + Console.WriteLine( "done" ); } @@ -420,6 +426,8 @@ namespace Server return; } + SocketPool.Create(); + MessagePump ms = m_MessagePump = new MessagePump( new Listener( Listener.Port ) ); timerThread.Start(); diff --git a/Server/Network/Listener.cs b/Server/Network/Listener.cs index 1824fc90e..72a1fe602 100644 --- a/Server/Network/Listener.cs +++ b/Server/Network/Listener.cs @@ -31,20 +31,15 @@ namespace Server.Network { private Socket m_Listener; private bool m_Disposed; - private int m_ThisPort; private Queue m_Accepted; private object m_AcceptedSyncRoot; private AsyncCallback m_OnAccept; + private AsyncCallback m_OnDisconnect; private static Socket[] m_EmptySockets = new Socket[0]; - public int UsedPort - { - get{ return m_ThisPort; } - } - private static int m_Port = 2593; public static int Port @@ -61,11 +56,11 @@ namespace Server.Network public Listener( int port ) { - m_ThisPort = port; m_Disposed = false; m_Accepted = new Queue(); m_AcceptedSyncRoot = ((ICollection)m_Accepted).SyncRoot; m_OnAccept = new AsyncCallback( OnAccept ); + m_OnDisconnect = new AsyncCallback( OnDisconnect ); m_Listener = Bind( IPAddress.Any, port ); @@ -89,7 +84,7 @@ namespace Server.Network { IPEndPoint ipep = new IPEndPoint( ip, port ); - Socket s = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); + Socket s = SocketPool.AcquireSocket(); try { @@ -99,7 +94,7 @@ namespace Server.Network s.Bind( ipep ); s.Listen( 8 ); - IAsyncResult res = s.BeginAccept( m_OnAccept, s ); + IAsyncResult res = s.BeginAccept( SocketPool.AcquireSocket(), 0, m_OnAccept, s ); return s; } @@ -111,8 +106,7 @@ namespace Server.Network try { s.Shutdown( SocketShutdown.Both ); } catch{} - try { s.Close(); } - catch{} + s.BeginDisconnect( true, m_OnDisconnect, s ); return null; } @@ -120,30 +114,24 @@ namespace Server.Network private void OnAccept( IAsyncResult asyncResult ) { - Socket listener = asyncResult.AsyncState as Socket; + Socket listener = (Socket)asyncResult.AsyncState; try { Socket socket = listener.EndAccept( asyncResult ); - if ( socket != null ) - { - SocketConnectEventArgs e = new SocketConnectEventArgs( socket ); - EventSink.InvokeSocketConnect( e ); + SocketConnectEventArgs e = new SocketConnectEventArgs( socket ); + EventSink.InvokeSocketConnect( e ); - if ( e.AllowConnection ) - { - lock ( m_AcceptedSyncRoot ) - m_Accepted.Enqueue( socket ); - } - else - { - try { socket.Shutdown( SocketShutdown.Both ); } - catch { } + if ( e.AllowConnection ) { + lock ( m_AcceptedSyncRoot ) + m_Accepted.Enqueue( socket ); + } + else { + try { socket.Shutdown( SocketShutdown.Both ); } + catch { } - try { socket.Close(); } - catch { } - } + socket.BeginDisconnect( true, m_OnDisconnect, socket ); } } catch @@ -151,12 +139,21 @@ namespace Server.Network } finally { - IAsyncResult res = listener.BeginAccept( m_OnAccept, listener ); + IAsyncResult res = listener.BeginAccept( SocketPool.AcquireSocket(), 0, m_OnAccept, listener ); } Core.Set(); } + private void OnDisconnect( IAsyncResult asyncResult ) + { + Socket s = (Socket)asyncResult.AsyncState; + + s.EndDisconnect( asyncResult ); + + SocketPool.ReleaseSocket( s ); + } + public Socket[] Slice() { Socket[] array; @@ -184,8 +181,7 @@ namespace Server.Network try { m_Listener.Shutdown( SocketShutdown.Both ); } catch {} - try { m_Listener.Close(); } - catch {} + m_Listener.BeginDisconnect( true, m_OnDisconnect, m_Listener ); m_Listener = null; } diff --git a/Server/Network/NetState.cs b/Server/Network/NetState.cs index 1fe7dcbc2..21d6fbfa2 100644 --- a/Server/Network/NetState.cs +++ b/Server/Network/NetState.cs @@ -50,7 +50,7 @@ namespace Server.Network { private SendQueue m_SendQueue; private bool m_Seeded; private bool m_Running; - private AsyncCallback m_OnReceive, m_OnSend; + private AsyncCallback m_OnReceive, m_OnSend, m_OnDisconnect; private MessagePump m_MessagePump; private ServerInfo[] m_ServerInfo; private IAccount m_Account; @@ -118,7 +118,7 @@ namespace Server.Network { private void InternalBeginReceive() { m_AsyncState |= AsyncState.Pending; - m_Socket.BeginReceive( m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.None, m_OnReceive, null ); + m_Socket.BeginReceive( m_RecvBuffer, 0, m_RecvBuffer.Length, SocketFlags.None, m_OnReceive, m_Socket ); } public static void Resume() { @@ -563,7 +563,7 @@ namespace Server.Network { if ( gram != null ) { try { - m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, null ); + m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket ); } catch { Dispose( false ); } @@ -610,7 +610,7 @@ namespace Server.Network { if ( gram != null ) { try { - m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, null ); + m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket ); return true; } catch { Dispose( false ); @@ -632,12 +632,10 @@ namespace Server.Network { } private void OnSend( IAsyncResult asyncResult ) { - if ( m_Socket == null ) { - return; - } + Socket s = (Socket)asyncResult.AsyncState; try { - int bytes = m_Socket.EndSend( asyncResult ); + int bytes = s.EndSend( asyncResult ); if ( bytes <= 0 ) { Dispose( false ); @@ -657,7 +655,7 @@ namespace Server.Network { } if ( gram != null ) { - m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, null ); + s.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, s ); } } catch { Dispose( false ); @@ -667,6 +665,7 @@ namespace Server.Network { public void Start() { m_OnReceive = new AsyncCallback( OnReceive ); m_OnSend = new AsyncCallback( OnSend ); + m_OnDisconnect = new AsyncCallback( OnDisconnect ); m_Running = true; @@ -707,12 +706,10 @@ namespace Server.Network { } private void OnReceive( IAsyncResult asyncResult ) { - if ( m_Socket == null ) { - return; - } + Socket s = (Socket)asyncResult.AsyncState; try { - int byteCount = m_Socket.EndReceive( asyncResult ); + int byteCount = s.EndReceive( asyncResult ); if ( byteCount > 0 ) { m_NextCheckActivity = DateTime.Now + TimeSpan.FromMinutes( 1.2 ); @@ -742,6 +739,15 @@ namespace Server.Network { } } + public void OnDisconnect( IAsyncResult asyncResult ) + { + Socket s = (Socket)asyncResult.AsyncState; + + s.EndDisconnect( asyncResult ); + + SocketPool.ReleaseSocket( s ); + } + public void Dispose() { Dispose( true ); } @@ -763,10 +769,7 @@ namespace Server.Network { } catch { } - try { - m_Socket.Close(); - } catch { - } + m_Socket.BeginDisconnect( true, m_OnDisconnect, m_Socket ); if ( m_RecvBuffer != null ) m_ReceiveBufferPool.ReleaseBuffer( m_RecvBuffer ); @@ -777,6 +780,7 @@ namespace Server.Network { m_RecvBuffer = null; m_OnReceive = null; m_OnSend = null; + m_OnDisconnect = null; m_Running = false; m_Disposed.Enqueue( this );