private Stopwatch _watch; //for testing #endregion Fields #region Constructors public SocketListener(int maxConnectionCount, int bufferSize) { _maxConnectionCount = maxConnectionCount; _bufferSize = bufferSize; _socketAsyncReceiveEventArgsPool = new SocketAsyncEventArgsPool(maxConnectionCount); _socketAsyncSendEventArgsPool = new SocketAsyncEventArgsPool(maxConnectionCount); _acceptedClientsSemaphore = new Semaphore(maxConnectionCount, maxConnectionCount); sendingQueue = new BlockingCollection<MessageData>(); sendMessageWorker = new Thread(new ThreadStart(SendQueueMessage)); for (int i = 0; i < maxConnectionCount; i++) { SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs(); socketAsyncEventArgs.Completed += OnIOCompleted; socketAsyncEventArgs.SetBuffer(new Byte[bufferSize], 0, bufferSize); _socketAsyncReceiveEventArgsPool.Push(socketAsyncEventArgs); } for (int i = 0; i < maxConnectionCount; i++) { SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs(); socketAsyncEventArgs.Completed += OnIOCompleted; socketAsyncEventArgs.SetBuffer(new Byte[bufferSize], 0, bufferSize); _socketAsyncSendEventArgsPool.Push(socketAsyncEventArgs); } waitSendEvent = new AutoResetEvent(false); }
/// <summary> /// Create an uninitialized server instance. /// To start the server listening for connection requests /// call the Init method followed by Start method. /// </summary> /// <param name="numConnections">Maximum number of connections to be handled simultaneously.</param> /// <param name="bufferSize">Buffer size to use for each socket I/O operation.</param> internal SocketListener(Int32 numConnections, Int32 bufferSize) { this.numConnectedSockets = 0; this.numConnections = numConnections; this.bufferSize = bufferSize; this.readWritePool = new SocketAsyncEventArgsPool(numConnections); this.semaphoreAcceptedClients = new Semaphore(numConnections, numConnections); // Preallocate pool of SocketAsyncEventArgs objects. for (Int32 i = 0; i < this.numConnections; i++) { SocketAsyncEventArgs readWriteEventArg = new SocketAsyncEventArgs(); readWriteEventArg.Completed += new EventHandler <SocketAsyncEventArgs>(OnIOCompleted); readWriteEventArg.SetBuffer(new Byte[this.bufferSize], 0, this.bufferSize); // Add SocketAsyncEventArg to the pool. this.readWritePool.Push(readWriteEventArg); } }
/// <summary> /// Create an uninitialized server instance. /// To start the server listening for connection requests /// call the Init method followed by Start method. /// </summary> /// <param name="numConnections">Maximum number of connections to be handled simultaneously.</param> /// <param name="bufferSize">Buffer size to use for each socket I/O operation.</param> internal SocketListener(Int32 numConnections, Int32 bufferSize) { this.numConnectedSockets = 0; this.numConnections = numConnections; this.bufferSize = bufferSize; this.readWritePool = new SocketAsyncEventArgsPool(numConnections); this.semaphoreAcceptedClients = new Semaphore(numConnections, numConnections); // Preallocate pool of SocketAsyncEventArgs objects. for (Int32 i = 0; i < this.numConnections; i++) { SocketAsyncEventArgs readWriteEventArg = new SocketAsyncEventArgs(); readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnIOCompleted); readWriteEventArg.SetBuffer(new Byte[this.bufferSize], 0, this.bufferSize); // Add SocketAsyncEventArg to the pool. this.readWritePool.Push(readWriteEventArg); } }
//__END variables for real app____________________________________________ //_______________________________________________________________________________ // Constructor. public SocketListener(SocketListenerSettings theSocketListenerSettings) { this.numberOfAcceptedSockets = 0; //for testing this.socketListenerSettings = theSocketListenerSettings; this.prefixHandler = new PrefixHandler(); this.messageHandler = new MessageHandler(); //Allocate memory for buffers. We are using a separate buffer space for //receive and send, instead of sharing the buffer space, like the Microsoft //example does. this.theBufferManager = new BufferManager(this.socketListenerSettings.BufferSize * this.socketListenerSettings.NumberOfSaeaForRecSend * this.socketListenerSettings.OpsToPreAllocate, this.socketListenerSettings.BufferSize * this.socketListenerSettings.OpsToPreAllocate); this.poolOfRecSendEventArgs = new SocketAsyncEventArgsPool(this.socketListenerSettings.NumberOfSaeaForRecSend); this.poolOfAcceptEventArgs = new SocketAsyncEventArgsPool(this.socketListenerSettings.MaxAcceptOps); // Create connections count enforcer this.theMaxConnectionsEnforcer = new Semaphore(this.socketListenerSettings.MaxConnections, this.socketListenerSettings.MaxConnections); //Microsoft's example called these from Main method, which you //can easily do if you wish. Init(); StartListen(); }
Process theProcess; //for testing only #endregion Fields #region Constructors //__END variables for real app____________________________________________ //_______________________________________________________________________________ // Constructor. public SocketListener(SocketListenerSettings theSocketListenerSettings) { if (Program.watchProgramFlow == true) //for testing { Program.testWriter.WriteLine("SocketListener constructor"); } if (Program.watchThreads == true) //for testing { theProcess = Process.GetCurrentProcess(); //for testing only DealWithThreadsForTesting("constructor"); } this.numberOfAcceptedSockets = 0; //for testing this.socketListenerSettings = theSocketListenerSettings; this.prefixHandler = new PrefixHandler(); this.messageHandler = new MessageHandler(); //Allocate memory for buffers. We are using a separate buffer space for //receive and send, instead of sharing the buffer space, like the Microsoft //example does. this.theBufferManager = new BufferManager(this.socketListenerSettings.BufferSize * this.socketListenerSettings.NumberOfSaeaForRecSend * this.socketListenerSettings.OpsToPreAllocate, this.socketListenerSettings.BufferSize * this.socketListenerSettings.OpsToPreAllocate); this.poolOfRecSendEventArgs = new SocketAsyncEventArgsPool(this.socketListenerSettings.NumberOfSaeaForRecSend); this.poolOfAcceptEventArgs = new SocketAsyncEventArgsPool(this.socketListenerSettings.MaxAcceptOps); // Create connections count enforcer this.theMaxConnectionsEnforcer = new Semaphore(this.socketListenerSettings.MaxConnections, this.socketListenerSettings.MaxConnections); //Microsoft's example called these from Main method, which you //can easily do if you wish. Init(); StartListen(); }
//____________________________________________________________________________ // This method is called when we need to create a new SAEA object to do //accept operations. The reason to put it in a separate method is so that //we can easily add more objects to the pool if we need to. //You can do that if you do NOT use a buffer in the SAEA object that does //the accept operations. internal SocketAsyncEventArgs CreateNewSaeaForAccept(SocketAsyncEventArgsPool pool) { //Allocate the SocketAsyncEventArgs object. SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs(); //SocketAsyncEventArgs.Completed is an event, (the only event,) //declared in the SocketAsyncEventArgs class. //See http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.completed.aspx. //An event handler should be attached to the event within //a SocketAsyncEventArgs instance when an asynchronous socket //operation is initiated, otherwise the application will not be able //to determine when the operation completes. //Attach the event handler, which causes the calling of the //AcceptEventArg_Completed object when the accept op completes. acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed); AcceptOpUserToken theAcceptOpToken = new AcceptOpUserToken(pool.AssignTokenId() + 10000); acceptEventArg.UserToken = theAcceptOpToken; return acceptEventArg; // accept operations do NOT need a buffer. //You can see that is true by looking at the //methods in the .NET Socket class on the Microsoft website. AcceptAsync does //not take require a parameter for buffer size. }