/// <summary> /// 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. /// </summary> /// <param name="pool"></param> /// <returns></returns> 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 require a parameter for buffer size. }
/// <summary> /// The e parameter passed from the AcceptEventArg_Completed method /// respents 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. /// </summary> /// <param name="e"></param> 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; // Let's destroy this socket, since it could be bad. HandleBadAccept(acceptEventArgs); // Jump out of the method return; } // 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 received/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.poolOfRecSendEventArgs.Push(acceptEventArgs); StartReceive(receiveSendEventArgs); }