关于socket通讯的server类(C#)

来源:互联网 发布:云计算ppt模板下载 编辑:程序博客网 时间:2024/04/29 05:00

最近项目完结,翻看之前的代码,发现了一些比较好的代码,贴出来给大家分享。有关于Socket通讯偷笑

using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;namespace Core.Sockets{    // 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.    public 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        protected 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         //        // <param name="numConnections">the maximum number of connections the sample is designed to handle simultaneously</param>        // <param name="receiveBufferSize">buffer size to use for each socket I/O operation</param>        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<SocketAsyncEventArgs>(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.            //        // <param name="localEndPoint">The endpoint which the server will listening         // for connection requests on</param>        public void Start(IPEndPoint localEndPoint)        {            // create the socket which listens for incoming connections            listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);            listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);            listenSocket.Bind(localEndPoint);            // start the server with a listen backlog of 100 connections            listenSocket.Listen(100);            // post accepts on the listening socket            StartAccept(null);        }        // Begins an operation to accept a connection request from the client         //        // <param name="acceptEventArg">The context object to use when issuing         // the accept operation on the server's listening socket</param>        public void StartAccept(SocketAsyncEventArgs acceptEventArg)        {            if (acceptEventArg == null)            {                acceptEventArg = new SocketAsyncEventArgs();                acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);            }            else            {                // socket must be cleared since the context object is being reused                acceptEventArg.AcceptSocket = null;            }            m_maxNumberAcceptedClients.WaitOne();            try            {                bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);                if (!willRaiseEvent)                {                    ProcessAccept(acceptEventArg);                }            }            catch            {            }        }        // 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);            // 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         //        // <param name="e">SocketAsyncEventArg associated with the completed receive operation</param>        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.        //        protected virtual 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);                //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        //        // <param name="e"></param>        protected 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);            }        }        protected 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);            m_maxNumberAcceptedClients.Release();            // Free the SocketAsyncEventArg so they can be reused by another client            m_readWritePool.Push(e);        }    }    }


0 0
原创粉丝点击