//____________________________________________________________________________ private void ProcessDisconnectAndCloseSocket(SocketAsyncEventArgs receiveSendEventArgs) { DataHoldingUserToken receiveSendToken = (DataHoldingUserToken)receiveSendEventArgs.UserToken; if (Program.watchProgramFlow == true) { Program.testWriter.WriteLine("\r\nProcessDisconnect(), id = " + receiveSendToken.TokenId); } if (receiveSendEventArgs.SocketError != SocketError.Success) { if (Program.watchProgramFlow == true) //for testing { Program.testWriter.WriteLine("ProcessDisconnect ERROR, id " + receiveSendToken.TokenId); } else if (Program.writeErrorsToLog == true) { Program.testWriter.WriteLine("ProcessDisconnect ERROR, id " + receiveSendToken.TokenId); } } if (Program.watchData == true) { Program.testWriter.WriteLine(ShowData(receiveSendToken)); } //This method closes the socket and releases all resources, both //managed and unmanaged. It internally calls Dispose. receiveSendEventArgs.AcceptSocket.Close(); //for testing Int32 sCount = receiveSendToken.theDataHolder.NumberOfMessagesSent; //create an object that we can write data to. receiveSendToken.CreateNewDataHolder(); // It is time to release this SAEA object. this.poolOfRecSendEventArgs.Push(receiveSendEventArgs); //Count down the number of connected clients as they disconnect. Interlocked.Decrement(ref this.clientsNowConnectedCount); Interlocked.Increment(ref this.numberOfConnectionsFinishedSuccessfully); Interlocked.Increment(ref this.totalNumberOfConnectionsFinished); this.theMaxConnectionsEnforcer.Release(); if (Program.showConnectAndDisconnect == true) { Program.testWriter.WriteLine(receiveSendToken.TokenId + " id disconnected. " + sCount + " = sent message count. " + this.clientsNowConnectedCount + " client connections to server from this machine. " + this.totalNumberOfConnectionsFinished + " clients finished.\r\n"); } //If all of the clients have finished sending //and receiving all of their messages, then we //need to finish. if (this.totalNumberOfConnectionsFinished == this.socketClientSettings.ConnectionsToRun) { this.completedAllTests = true; FinishTest(); } }
//____________________________________________________________________________ // Initializes the client by preallocating reusable buffers and // context objects (SocketAsyncEventArgs objects). // It is NOT mandatory that you preallocate them or reuse them. // In fact, you would probably NOT normally do this on a client. // But, for testing we want to be able to throw a lot of connections at // our socket server from a LAN. And this is a way to do it. // private void Init() { if (Program.watchProgramFlow == true) //for testing { Program.testWriter.WriteLine("Init method"); Program.testWriter.WriteLine("Creating connect SocketAsyncEventArgs pool"); } SocketAsyncEventArgs connectEventArg; // preallocate pool of SocketAsyncEventArgs objects for connect operations for (int i = 0; i < this.socketClientSettings.MaxConnectOps; i++) { connectEventArg = CreateNewSaeaForConnect(poolOfConnectEventArgs); // add SocketAsyncEventArg to the pool this.poolOfConnectEventArgs.Push(connectEventArg); } if (Program.watchProgramFlow == true) //for testing { Program.testWriter.WriteLine(""); } // Allocate one large byte buffer block, which all I/O operations will use a piece of. //This gaurds against memory fragmentation. this.bufferManager.InitBuffer(); //The pool that we built ABOVE is for SocketAsyncEventArgs objects that do // connect operations. Now we will build a separate pool for //SocketAsyncEventArgs objects that do receive/send operations. //One reason to separate them is that connect //operations do NOT need a buffer, but receive/send operations do. //You can see that is true by looking at the //methods in the .NET Socket class on the Microsoft website. //ReceiveAsync and SendAsync take //a parameter for buffer size in SocketAsyncEventArgs.Buffer. //Preallocate pool of SocketAsyncEventArgs for receive/send operations. if (Program.watchProgramFlow == true) //for testing { Program.testWriter.WriteLine("Creating receive/send SocketAsyncEventArgs pool"); } SocketAsyncEventArgs eventArgObjectForPool; for (int i = 0; i < this.socketClientSettings.NumberOfSaeaForRecSend; i++) { //If you have different needs for the send versus the receive sockets, then //you might want to allocate a separate pool of SocketAsyncEventArgs for send //operations instead of having SocketAsyncEventArgs that do both receiving //and sending operations. //Allocate the SocketAsyncEventArgs object. eventArgObjectForPool = new SocketAsyncEventArgs(); // assign a byte buffer from the buffer block to //this particular SocketAsyncEventArg object this.bufferManager.SetBuffer(eventArgObjectForPool); //Since we assigned a buffer like that, you can NOT just add more of //these send/receive SAEA objects if you run out of them. //Attach the receive/send-operation-SocketAsyncEventArgs object //to its event handler. Since this SocketAsyncEventArgs object is used //for both receive and send operations, whenever either of those //completes, the IO_Completed method will be called. eventArgObjectForPool.Completed += new EventHandler <SocketAsyncEventArgs>(IO_Completed); DataHoldingUserToken receiveSendToken = new DataHoldingUserToken(eventArgObjectForPool.Offset, eventArgObjectForPool.Offset + this.socketClientSettings.BufferSize, this.socketClientSettings.ReceivePrefixLength, this.socketClientSettings.SendPrefixLength, (this.poolOfRecSendEventArgs.AssignTokenId() + 1000000)); //Create an object that we can write data to, and remove as an object //from the UserToken, if we wish. receiveSendToken.CreateNewDataHolder(); eventArgObjectForPool.UserToken = receiveSendToken; // add this SocketAsyncEventArg object to the pool. this.poolOfRecSendEventArgs.Push(eventArgObjectForPool); } Console.WriteLine("Object pools built."); }