Active User Count Without Global.asaby Josh Painter( Webmaster of Toastforums.com) Introduction Introduction
So you've got your killer website up and running, and you're wanting to add a few little "perks." One of the hottest trends today is to show an "Active User Count" that shows exactly how many people are currently connected to your website. Many articles have already been written showing exactly how to do this using the global.asa file, so I won't even bother to explain that method. ASP 101 has a great article explaining the global.asa method of counting active users.What I'd like to do is show you how to not use the global.asa file. I'm not saying using the global.asa file is bad--far from it. If you can use it then please do; it will probably yield a bit better performance. But there are many reasons why you might not want (or simply can't) use a global.asa file. Perhaps your host does not allow a global.asa. Maybe your site is hosted in a subdirectory of an existing site, and they won't set up an IIS application for you, so a global.asa file will do you no good. Or you might even not want to mess with an existing global.asa file, or not have access to do so. Personally, I needed to have this functionality for a web application I've been building (shameless link) and one of my design goals was that the Active User Count would NOT require use of a global.asa. I didn't want to bother with helping webmasters try to merge my code in with an existing global.asa, or guide them through setting up an existing IIS application so they could use my global.asa. Many of them couldn't even if they know how, because their web host doesn't allow it. So, this is the solution. Quick Explanation
To make a manual Active User Count, we have a few options about where to store the active users on the server. We could store them in a database, in a text file, or in server memory in an Application variable. I chose to go with Application variables. Databases may be fast, but I don't like to query a database on *every* hit to a page unless absolutely necessary. Text files could get cumbersome, and I don't want to worry about file permissions. So the logical choice is Application variables. Application variables are very fast to access, since they reside in the web server's memory, and are available on just about every ASP web host out there. I make use of three Application variables: one that holds the number of online users, another that holds a list of unique users and the last time of their activity, and the final variable remembers when the last cleanup occurred. We'll use the SessionID for a unique key of each user, and the simple Now() function to tag each SessionID with the time of last activity. So, without any more explaining, here is the "LogActiveUser" function: LogActiveUser Routine Sub LogActiveUser Dim strActiveUserList Dim intUserStart, intUserEnd Dim strUser Dim strDate
strActiveUserList = Application("ActiveUserList")
If Instr(1, strActiveUserList, Session.SessionID) > 0 Then Application.Lock intUserStart = Instr(1, strActiveUserList, Session.SessionID) intUserEnd = Instr(intUserStart, strActiveUserList, "|") strUser = Mid(strActiveUserList, intUserStart, intUserEnd - intUserStart) strActiveUserList = Replace(strActiveUserList, strUser, Session.SessionID & ":" & Now()) Application("ActiveUserList") = strActiveUserList Application.UnLock Else Application.Lock Application("ActiveUsers") = CInt(Application("ActiveUsers")) + 1 Application("ActiveUserList") = Application("ActiveUserList") & Session.SessionID & ":" & Now() & "|" Application.UnLock End If End Sub
|
So let's take this line by line. First, we are copying the Active User list into a local variable. We are going to be doing lots of string manipulation, and we don't want to make a call out to the Application Variables collection every time we need to inspect the Active User list. Then we need to check to see if this user is already in the list. We do this by the simple Instr call to see if his SessionID exists. If it doesn't, its easy--we just add one to the ActiveUsers parameter and add this new SessionID and current time to the Active User list. If the SessionID already exists, we've got a bit more work to do. We've got to find this user in the list and update his time stamp. The ActiveUserList variable will look something like this at any one time:
| 716763555:1/4/2001 11:10:23 PM|616733525:1/4/2001 11:11:45 PM|8616433235:1/4/2001 11:15:58 PM | So we need to extract the user that we're looking for, change his timestamp to Now(), and insert him back in the list. Pretty easy to do. First we find the beginning of the user by searching for SessionID. Since the users are delimited by a pipe "|" symbol, we just search for the pipe starting with the beginning of the SessionID to find the end of the User's timestamp. Now that we have the beginning and the end, we can just replace this entire "chunk" of the string with the SessionID and current timestamp. This will effectively "reset" the user's timestamp. But, how do we clean up ActiveUsers as their timestamps get old? Let's look at the ActiveUserCleanup routine. ActiveUserCleanup Routine
Sub ActiveUserCleanup Dim ix Dim intUsers Dim strActiveUserList Dim aActiveUsers Dim intActiveUserCleanupTime Dim intActiveUserTimeout
intActiveUserCleanupTime = 1 'In minutes, how often should the ActiveUserList be cleaned up. intActiveUserTimeout = 20 'In minutes, how long before a User is considered Inactive and is deleted from ActiveUserList
If Application("ActiveUserList") = "" Then Exit Sub
If DateDiff("n", Application("ActiveUsersLastCleanup"), Now()) > intActiveUserCleanupTime Then
Application.Lock Application("ActiveUsersLastCleanup") = Now() Application.Unlock
intUsers = 0 strActiveUserList = Application("ActiveUserList") strActiveUserList = Left(strActiveUserList, Len(strActiveUserList) - 1)
aActiveUsers = Split(strActiveUserList, "|")
For ix = 0 To UBound(aActiveUsers) If DateDiff("n", Mid(aActiveUsers(ix), Instr(1, aActiveUsers(ix), ":") + 1, Len(aActiveUsers(ix))), Now()) > intActiveUserTimeout Then aActiveUsers(ix) = "XXXX" Else intUsers = intUsers + 1 End If Next
strActiveUserList = Join(aActiveUsers, "|") & "|" strActiveUserList = Replace(strActiveUserList, "XXXX|", "")
Application.Lock Application("ActiveUserList") = strActiveUserList Application("ActiveUsers") = intUsers Application.UnLock
End If
End Sub |
Let's look at this routine line by line. The first thing we do is set some internal variables that decide when to cleanup, and how long before a User is considered Inactive. The variables intActiveUserCleanupTime and intActiveUserTimeout control these times, respectively. If the ActiveUserList is blank, we have nothing to do here, so Exit Sub. If the difference (in minutes) between the time we last ran the cleanup procedure and the time right now is greater than intActiveUserCleanupTime, let's run cleanup (this is better for performance--we only want to run cleanup every minute or so, not every time the calling script is hit). Immediately set the ActiveUsersLastCleanup variable to Now, so if another script calls this procedure while we are doing our work it will think that it is not yet time to run cleanup. Now we will copy the ActiveUserList to a local variable for increased performance and convert it to an array so we can loop through all the users. We loop through each user, and if we find a timestamp that is older than the intActiveUserTimeout variable, we will replace the entire User with "XXXX", and delete him later (we must do this because VBScript does not natively support any advanced array handling like deleting or inserting elements). Now that we've marked inactive users, we'll convert the Array back to a string. We end the string with our delimiter "|" to make the next step easier. Replace any occurences of "XXXX|" that we find to "", effectively deleting the user from the ActiveUserList. Now its time to store the variables back into the Application variables. Getting it up and running with your Site This should be relatively easy. Just put these functions in a file and include it with any pages that will need to log Active Users and show an Activer User Count. So your script might look something like this:
<%
Call LogActiveUser() Call ActiveUserCleanup()
Response.Write "There are " & Application("ActiveUsers") & " active users currently online."
%>
|
Shameless Plug If you would like to see this code in action, head over to toastforums.com. See the "Current Online Forum Users" up in the right corner? That is using this exact code! Oh, and if you need a free ASP message board for your website, try Toast! Happy coding! Josh Painter | DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |
More ASP Code Articles More By aspfree developerWorks - FREE Tools! | Hear how IBM Rational Project and Portfolio Management integrated solutions help teams put the right tools and processes in place to maximize the effectiveness and efficiency of project teams and ensure that the business vision is being executed correctly. Learn how to automate and integrate requirements prioritization, top-down project planning, communications and controls, and methodology deployment to keep your scope, costs, and schedules under control. Tackle with an end-to-end approach the management of scope and scope changes, usage of methodology to control and empower project teams, and optimization of resources to align activity costs with the overall project plan. FREE! Go There Now!
| | | | Learn field-tested SOA principles, methodology, technology and implementation from the global SOA market leader - in a new e-book by an IBM SOA expert. Written by IBM Certified SOA Solution Designer Bobby Woolf, "Exploring IBM SOA Technology & Practice" is the ultimate insider's guide to SOA - a PDF e-book packed cover to cover with IBM's specific advice on how to make your SOA implementation a success. FREE! Go There Now!
| | | | Achieving true agility is a never-ending effort. We will showcase how you can become agile incrementally, a few practices at the time.Which practices should any agile team strive to adopt? What additional practices should you consider based on your needs to scale? Adopting practices are however made much easier with the right tool support. What about if your tools adapt to your practices? We will take a look at how the Jazz technology can be leveraged to make your process change the behavior of your tools. FREE! Go There Now!
| | | | Learn how to implement a build management system that uses and extends your existing automation technologies. This tutorial shows, step-by-step, how to install and configure IBM Rational Build Forge to manage builds for Jakarta Tomcat from source code. FREE! Go There Now!
| | | | Ken Krugler, co-founder of code search company Krugle, and Laura Merling, vice president of Marketing and Business Development for Krugle, join to talk about the ins and outs of code search and what it means as a new feature for developerWorks users. FREE! Go There Now!
| | | | Rational Modeling Extension for Microsoft .NET enhances usability for code generation supporting a more intelligent refactoring. The latest enhancements enable organizations with Java and .NET systems and software development maintain architectural integrity across heterogeneous platforms. FREE! Go There Now!
| | | | Get a free trial download of IBM Lotus Forms V3.0 (formerly Workplace Forms), which provides a zero-footprint eForms solution to help you automate and move forms-based business processes off the desktop and onto the Web. With Lotus Forms, you can extend applications beyond the firewall by creating a single electronic form document ready for use in both thick and Web 2.0 thin client format. FREE! Go There Now!
| | | | Get a free trial download of the latest version of IBM Rational Functional Tester V7.0.1. Rational Functional Tester is an automated functional and regression testing solution for QA teams concerned with the quality of their Java, Microsoft Visual Studio .NET, and Web-based applications. FREE! Go There Now!
| | | | Try the latest version of IBM Rational Manual Tester V7.0.1 by downloading a free trial from IBM developerWorks. This manual test authoring and execution tool promotes test step reuse to reduce the impact of software change on testers and business analysts and addresses the needs of teams performing at least a portion of their testing manually. FREE! Go There Now!
| | | | The unprecedented scope of a service-oriented architecture (SOA) initiative brings to the forefront a number of management and governance issues that were sidestepped in the past. The key to a successful SOA implementation is managing and governing activities throughout the entire SOA delivery lifecycle by ensuring that services conform to the needs of all of the business’s stakeholders. Learn how service lifecycle management allows the business to ensure that the process by which services are defined, created, tested, deployed, optimized and retired is manageable, repeatable and auditable. FREE! Go There Now!
| | | | All FREE IBM® developerWorks Tools! | |