private void ProcessSend(SocketAsyncEventArgs workerEventArgs)
        {
            DataHoldingUserToken <T> token = (DataHoldingUserToken <T>)workerEventArgs.UserToken;

            token.WriteDataBytesSent += workerEventArgs.BytesTransferred;

            // --- Logging / Debugging
            _trace.Sent(_settings.CustomState, token, workerEventArgs.GetRemoteIpEndPoint(), workerEventArgs.BytesTransferred);
            // ---

            if (workerEventArgs.SocketError != SocketError.Success)
            {
                token.Reset();
                CloseClientSocket(workerEventArgs);

                return;
            }

            if (token.WriteDataBytesRemaining > 0)
            {
                // If some of the bytes in the message have NOT been sent,
                // then we will need to post another send operation
                StartSend(workerEventArgs);
            }
            else
            {
                if (token.CloseAfterSend)
                {
                    CloseClientSocket(workerEventArgs);
                }
                else
                {
                    StartReceive(workerEventArgs);
                }
            }
        }
        /// <summary>
        /// Begin sending data
        /// </summary>
        /// <param name="workerEventArgs"></param>
        private void StartSend(SocketAsyncEventArgs workerEventArgs)
        {
            DataHoldingUserToken <T> token = (DataHoldingUserToken <T>)workerEventArgs.UserToken;

            if (token.WriteDataBytesRemaining <= _settings.IoBufferSize)
            {
                // Whole remaining message will fit in buffer.
                workerEventArgs.SetBuffer(token.WriteBufferOffset, token.WriteDataBytesRemaining);
                Buffer.BlockCopy(token.WriteData, token.WriteDataBytesSent, workerEventArgs.Buffer, token.WriteBufferOffset, token.WriteDataBytesRemaining);

                // --- Logging / Debugging
                _trace.Sending(_settings.CustomState, token, workerEventArgs.GetRemoteIpEndPoint(), workerEventArgs.Buffer, token.WriteBufferOffset, token.WriteDataBytesRemaining);
                // ---
            }
            else
            {
                // Message to big to all go in buffer.

                workerEventArgs.SetBuffer(token.WriteBufferOffset, _settings.IoBufferSize);
                Buffer.BlockCopy(token.WriteData, token.WriteDataBytesSent, workerEventArgs.Buffer, token.WriteBufferOffset, _settings.IoBufferSize);

                // We update the token.WriteDataBytesSent once the Sending has been confirmed.

                // --- Logging / Debugging
                _trace.Sending(_settings.CustomState, token, workerEventArgs.GetRemoteIpEndPoint(), workerEventArgs.Buffer, token.WriteBufferOffset, _settings.IoBufferSize);
                // ---
            }


            bool runningAsync = workerEventArgs.AcceptSocket.SendAsync(workerEventArgs);

            if (!runningAsync)
            {
                ProcessSend(workerEventArgs);
            }
        }