//____________________________________________________________________________ //The e parameter passed from the AcceptEventArg_Completed method //represents the SocketAsyncEventArgs object that did //the accept operation. in this method we'll do the handoff from it to the //SocketAsyncEventArgs object that will do receive/send. private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs) { // This is when there was an error with the accept op. That should NOT // be happening often. It could indicate that there is a problem with // that socket. If there is a problem, then we would have an infinite // loop here, if we tried to reuse that same socket. if (acceptEventArgs.SocketError != SocketError.Success) { // Loop back to post another accept op. Notice that we are NOT // passing the SAEA object here. LoopToStartAccept(); AcceptOpUserToken theAcceptOpToken = (AcceptOpUserToken)acceptEventArgs.UserToken; Program.testWriter.WriteLine("SocketError, accept id " + theAcceptOpToken.TokenId); //Let's destroy this socket, since it could be bad. HandleBadAccept(acceptEventArgs); //Jump out of the method. return; } Int32 max = Program.maxSimultaneousClientsThatWereConnected; Int32 numberOfConnectedSockets = Interlocked.Increment(ref this.numberOfAcceptedSockets); if (numberOfConnectedSockets > max) { Interlocked.Increment(ref Program.maxSimultaneousClientsThatWereConnected); } //Now that the accept operation completed, we can start another //accept operation, which will do the same. Notice that we are NOT //passing the SAEA object here. LoopToStartAccept(); // Get a SocketAsyncEventArgs object from the pool of receive/send op //SocketAsyncEventArgs objects SocketAsyncEventArgs receiveSendEventArgs = this.poolOfRecSendEventArgs.Pop(); //Create sessionId in UserToken. ((DataHoldingUserToken)receiveSendEventArgs.UserToken).CreateSessionId(); //A new socket was created by the AcceptAsync method. The //SocketAsyncEventArgs object which did the accept operation has that //socket info in its AcceptSocket property. Now we will give //a reference for that socket to the SocketAsyncEventArgs //object which will do receive/send. receiveSendEventArgs.AcceptSocket = acceptEventArgs.AcceptSocket; //We have handed off the connection info from the //accepting socket to the receiving socket. So, now we can //put the SocketAsyncEventArgs object that did the accept operation //back in the pool for them. But first we will clear //the socket info from that object, so it will be //ready for a new socket when it comes out of the pool. acceptEventArgs.AcceptSocket = null; this.poolOfAcceptEventArgs.Push(acceptEventArgs); StartReceive(receiveSendEventArgs); }
//____________________________________________________________________________ // 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. }
//____________________________________________________________________________ //Display thread info. //Overloaded. //Use this one in method where AcceptOpUserToken is available. // private void DealWithThreadsForTesting(string methodName, AcceptOpUserToken theAcceptOpToken) { StringBuilder sb = new StringBuilder(); string hString = hString = ". Socket handle " + theAcceptOpToken.socketHandleNumber; sb.Append(" In " + methodName + ", acceptToken id " + theAcceptOpToken.TokenId + ". Thread id " + Thread.CurrentThread.ManagedThreadId + hString + "."); sb.Append(DealWithNewThreads()); Program.testWriter.WriteLine(sb.ToString()); }
//____________________________________________________________________________ // 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. }