diff --git a/FastTunnel.Core/AsyncListener.cs b/FastTunnel.Core/AsyncListener.cs index a0d00ab..f9c93d0 100644 --- a/FastTunnel.Core/AsyncListener.cs +++ b/FastTunnel.Core/AsyncListener.cs @@ -20,6 +20,7 @@ namespace FastTunnel.Core int m_numConnectedSockets; + bool shutdown = false; IListenerDispatcher _requestDispatcher; Socket listenSocket; @@ -38,6 +39,7 @@ namespace FastTunnel.Core public void Listen(IListenerDispatcher requestDispatcher) { + shutdown = false; _requestDispatcher = requestDispatcher; listenSocket.Listen(100); @@ -45,7 +47,30 @@ namespace FastTunnel.Core StartAccept(null); } - public void StartAccept(SocketAsyncEventArgs acceptEventArg) + public void ShutdownAndClose() + { + if (shutdown) + return; + + try + { + if (listenSocket.Connected) + { + listenSocket.Shutdown(SocketShutdown.Both); + } + } + catch (Exception) + { + } + finally + { + shutdown = true; + listenSocket.Close(); + Interlocked.Decrement(ref m_numConnectedSockets); + } + } + + private void StartAccept(SocketAsyncEventArgs acceptEventArg) { if (acceptEventArg == null) { @@ -78,6 +103,7 @@ namespace FastTunnel.Core // Accept the next connection request StartAccept(e); + // 将此客户端交由Dispatcher进行管理 _requestDispatcher.Dispatch(accept); } else @@ -90,21 +116,5 @@ namespace FastTunnel.Core { ProcessAccept(e); } - - public void ShutdownAndClose() - { - try - { - listenSocket.Shutdown(SocketShutdown.Both); - } - catch (Exception) - { - } - finally - { - listenSocket.Close(); - Interlocked.Decrement(ref m_numConnectedSockets); - } - } } } diff --git a/FastTunnel.Core/Server.cs b/FastTunnel.Core/Server.cs deleted file mode 100644 index ffd4e33..0000000 --- a/FastTunnel.Core/Server.cs +++ /dev/null @@ -1,252 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; - -namespace FastTunnel.Core -{ - // Implements the connection logic for the socket server. - // After accepting a connection, all data read from the client - // is sent back to the client. The read and echo back to the client pattern - // is continued until the client disconnects. - class Server - { - private int m_numConnections; // the maximum number of connections the sample is designed to handle simultaneously - private int m_receiveBufferSize;// buffer size to use for each socket I/O operation - BufferManager m_bufferManager; // represents a large reusable set of buffers for all socket operations - const int opsToPreAlloc = 2; // read, write (don't alloc buffer space for accepts) - Socket listenSocket; // the socket used to listen for incoming connection requests - // pool of reusable SocketAsyncEventArgs objects for write, read and accept socket operations - SocketAsyncEventArgsPool m_readWritePool; - int m_totalBytesRead; // counter of the total # bytes received by the server - int m_numConnectedSockets; // the total number of clients connected to the server - Semaphore m_maxNumberAcceptedClients; - - // Create an uninitialized server instance. - // To start the server listening for connection requests - // call the Init method followed by Start method - // - // the maximum number of connections the sample is designed to handle simultaneously - // buffer size to use for each socket I/O operation - public Server(int numConnections, int receiveBufferSize) - { - m_totalBytesRead = 0; - m_numConnectedSockets = 0; - m_numConnections = numConnections; - m_receiveBufferSize = receiveBufferSize; - // allocate buffers such that the maximum number of sockets can have one outstanding read and - //write posted to the socket simultaneously - m_bufferManager = new BufferManager(receiveBufferSize * numConnections * opsToPreAlloc, - receiveBufferSize); - - m_readWritePool = new SocketAsyncEventArgsPool(numConnections); - m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections); - } - - // Initializes the server by preallocating reusable buffers and - // context objects. These objects do not need to be preallocated - // or reused, but it is done this way to illustrate how the API can - // easily be used to create reusable objects to increase server performance. - // - public void Init() - { - // Allocates one large byte buffer which all I/O operations use a piece of. This gaurds - // against memory fragmentation - m_bufferManager.InitBuffer(); - - // preallocate pool of SocketAsyncEventArgs objects - SocketAsyncEventArgs readWriteEventArg; - - for (int i = 0; i < m_numConnections; i++) - { - //Pre-allocate a set of reusable SocketAsyncEventArgs - readWriteEventArg = new SocketAsyncEventArgs(); - readWriteEventArg.Completed += new EventHandler(IO_Completed); - readWriteEventArg.UserToken = new AsyncUserToken(); - - // assign a byte buffer from the buffer pool to the SocketAsyncEventArg object - m_bufferManager.SetBuffer(readWriteEventArg); - - // add SocketAsyncEventArg to the pool - m_readWritePool.Push(readWriteEventArg); - } - } - - // Starts the server such that it is listening for - // incoming connection requests. - // - // The endpoint which the server will listening - // for connection requests on - public void Start(IPEndPoint localEndPoint) - { - // create the socket which listens for incoming connections - listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - listenSocket.Bind(localEndPoint); - // start the server with a listen backlog of 100 connections - listenSocket.Listen(100); - - // post accepts on the listening socket - StartAccept(null); - - //Console.WriteLine("{0} connected sockets with one outstanding receive posted to each....press any key", m_outstandingReadCount); - Console.WriteLine("Press any key to terminate the server process...."); - Console.ReadKey(); - } - - // Begins an operation to accept a connection request from the client - // - // The context object to use when issuing - // the accept operation on the server's listening socket - public void StartAccept(SocketAsyncEventArgs acceptEventArg) - { - if (acceptEventArg == null) - { - acceptEventArg = new SocketAsyncEventArgs(); - acceptEventArg.Completed += new EventHandler(AcceptEventArg_Completed); - } - else - { - // socket must be cleared since the context object is being reused - acceptEventArg.AcceptSocket = null; - } - - m_maxNumberAcceptedClients.WaitOne(); - bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg); - if (!willRaiseEvent) - { - ProcessAccept(acceptEventArg); - } - } - - // This method is the callback method associated with Socket.AcceptAsync - // operations and is invoked when an accept operation is complete - // - void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) - { - ProcessAccept(e); - } - - private void ProcessAccept(SocketAsyncEventArgs e) - { - Interlocked.Increment(ref m_numConnectedSockets); - Console.WriteLine("Client connection accepted. There are {0} clients connected to the server", - m_numConnectedSockets); - - // Get the socket for the accepted client connection and put it into the - //ReadEventArg object user token - SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop(); - ((AsyncUserToken)readEventArgs.UserToken).Socket = e.AcceptSocket; - - // As soon as the client is connected, post a receive to the connection - bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs); - if (!willRaiseEvent) - { - ProcessReceive(readEventArgs); - } - - // Accept the next connection request - StartAccept(e); - } - - // This method is called whenever a receive or send operation is completed on a socket - // - // SocketAsyncEventArg associated with the completed receive operation - void IO_Completed(object sender, SocketAsyncEventArgs e) - { - // determine which type of operation just completed and call the associated handler - switch (e.LastOperation) - { - case SocketAsyncOperation.Receive: - ProcessReceive(e); - break; - case SocketAsyncOperation.Send: - ProcessSend(e); - break; - default: - throw new ArgumentException("The last operation completed on the socket was not a receive or send"); - } - } - - // This method is invoked when an asynchronous receive operation completes. - // If the remote host closed the connection, then the socket is closed. - // If data was received then the data is echoed back to the client. - // - private void ProcessReceive(SocketAsyncEventArgs e) - { - // check if the remote host closed the connection - AsyncUserToken token = (AsyncUserToken)e.UserToken; - if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) - { - //increment the count of the total bytes receive by the server - Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred); - Console.WriteLine("The server has read a total of {0} bytes", m_totalBytesRead); - - //echo the data received back to the client - e.SetBuffer(e.Offset, e.BytesTransferred); - bool willRaiseEvent = token.Socket.SendAsync(e); - if (!willRaiseEvent) - { - ProcessSend(e); - } - } - else - { - CloseClientSocket(e); - } - } - - // This method is invoked when an asynchronous send operation completes. - // The method issues another receive on the socket to read any additional - // data sent from the client - // - // - private void ProcessSend(SocketAsyncEventArgs e) - { - if (e.SocketError == SocketError.Success) - { - // done echoing data back to the client - AsyncUserToken token = (AsyncUserToken)e.UserToken; - // read the next block of data send from the client - bool willRaiseEvent = token.Socket.ReceiveAsync(e); - if (!willRaiseEvent) - { - ProcessReceive(e); - } - } - else - { - CloseClientSocket(e); - } - } - - private void CloseClientSocket(SocketAsyncEventArgs e) - { - AsyncUserToken token = e.UserToken as AsyncUserToken; - - // close the socket associated with the client - try - { - token.Socket.Shutdown(SocketShutdown.Send); - } - // throws if client process has already closed - catch (Exception) { } - token.Socket.Close(); - - // decrement the counter keeping track of the total number of clients connected to the server - Interlocked.Decrement(ref m_numConnectedSockets); - - // Free the SocketAsyncEventArg so they can be reused by another client - m_readWritePool.Push(e); - - m_maxNumberAcceptedClients.Release(); - Console.WriteLine("A client has been disconnected from the server. There are {0} clients connected to the server", m_numConnectedSockets); - } - } - - internal class AsyncUserToken - { - public System.Net.Sockets.Socket Socket { get; set; } - } -} diff --git a/FastTunnel.Core/SuiDao.Core.csproj.user b/FastTunnel.Core/SuiDao.Core.csproj.user deleted file mode 100644 index 966b4ff..0000000 --- a/FastTunnel.Core/SuiDao.Core.csproj.user +++ /dev/null @@ -1,6 +0,0 @@ - - - - true - - \ No newline at end of file