2

我想知道我网站上的在线访问者数量。我进行了研究并找到了两种解决方案。

来源: ASP.NET 中的 Code Project
Online 活动用户计数器

它易于设置和使用,但它也增加了每个 Ajax 请求/响应的用户数。仅我的主页就有 12 个 Ajax 请求(一个页面有 8 个请求,另一个页面有 4 个请求)。这大大增加了用户数量。

资料来源:Stack Overflow Q/A
统计访客人数 这一项与上一项完全相同。

来源:ASP.Net 论坛 如何使用 C# 查看“谁在线”

这个看起来比前两个好。这是此解决方案的详细代码。

void Application_Start(object sender, EventArgs e) 
    {
        // Code that runs on application startup
        HttpContext.Current.Application["visitors_online"] = 0;
    }

void Session_Start(object sender, EventArgs e) 
    {
        Session.Timeout = 20; //'20 minute timeout
        HttpContext.Current.Application.Lock();
        Application["visitors_online"] = Convert.ToInt64(HttpContext.Current.Application["visitors_online"]) + 1;
        HttpContext.Current.Application.UnLock();
    }

void Session_End(object sender, EventArgs e) 
    {
        HttpContext.Current.Application.Lock();
        Application["visitors_online"] = Convert.ToInt64(HttpContext.Current.Application["visitors_online"]) - 1;
        HttpContext.Current.Application.UnLock();
    }

它似乎可以忽略每个 Ajax 响应的计数增加,但它仍然会为每个页面刷新或页面请求加起来。

有什么方法可以准确统计 ASP.Net 中的在线访问者数量吗?

4

6 回答 6

5

您永远无法获得完全准确的数字:无法(可靠地)检测到用户“已导航到另一个站点”(并离开了您的站点)或该用户“关闭了浏览器”。

Session_Start/Session_End 方式的问题是 Session_End 仅在“InProc”会话中调用,如果会话存储在 StateServer 或 SqlServer 中则不会。

你可以做的:

  • Dictionary<string, DateTime>在 Application 范围内持有 a 。此存储的会话 ID(字符串键)与最近访问的时间(DateTime 值)相对应
  • 对于具有有效会话的每个请求,在字典中查找会话条目并更新其最新访问时间(如果未找到,则添加新条目)
  • 当您想获取在线用户数时,首先遍历字典中的所有条目并删除会话超时已过去的项目。剩余的计数是在线用户数。

一个问题(至少):如果一个用户同时使用两个浏览器,他打开了两个会话并且被计算为双倍。如果用户总是登录,也许你可以依靠 login-id 而不是 session-id。

于 2012-07-09T10:41:57.200 回答
1

我想提出完全不同的建议:尝试为此使用 Google Analytic。这些家伙添加了测试版功能,现在可以跟踪在线统计数据。

编辑:你不明白我。我提到不是标准的谷歌分析功能。我提到了新功能——实时。查看下一篇文章了解详情 -您的网站现在发生了什么?或观看此视频 - Google Analytics(分析)实时测试版

于 2012-07-11T05:19:01.027 回答
0

Hans 的解决方案非常棒,并且完全符合我的要求,但我最近在 MSDN 上发现了这篇文章,这似乎是实现此目的的最佳实践。

参考:http: //msdn.microsoft.com/en-AU/library/system.web.httprequest.anonymousid.aspx

全球.asax

void Application_Start(Object sender, EventArgs e)
    {
        // Initialize user count property
        Application["UserCount"] = 0;
    }

public void AnonymousIdentification_Creating(Object sender, AnonymousIdentificationEventArgs e)
    {
    // Change the anonymous id
    e.AnonymousID = "mysite.com_Anonymous_User_" + DateTime.Now.Ticks;

    // Increment count of unique anonymous users
    Application["UserCount"] = Int32.Parse(Application["UserCount"].ToString()) + 1;
}

.ASPX 文件

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
  void Page_Load(object sender, EventArgs e)
    {
      if (Application["UserCount"] != null)
      {
          lblUserCount.Text = Application["UserCount"].ToString();
          lblCurrentUser.Text = Request.AnonymousID;
      }
  }    
</script>


<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>AnonymousID Example</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        Number of users: 
        <asp:Label ID="lblUserCount" Runat="server"></asp:Label><br />
    Current user:
        <asp:Label ID="lblCurrentUser" Runat="server"></asp:Label><br />
    </div>
    </form>
</body>
</html>
于 2013-04-17T05:33:57.863 回答
0

为什么不检查用户 IP 以获得唯一访问。将它们添加到哈希集中,这样您就可以做一些不错的事情,例如使用位置 API 制作热图:

 // count users online on all desktopsites
        void Session_Start(object sender, EventArgs e)
        {
            try
            {
                // lock application object
                Application.Lock();

                // get hashset containing all online ip adresses
                var ips = (HashSet<string>)Application["visitors_online_list_ip"];

                // get user ip
                var ip = HttpContext.Current.Request.UserHostAddress;

                // add ip to hashset
                ips.Add(ip);

                // store ip in session to delete when session ends
                Session["ip"] = ip;

                // save hashset
                Application["visitors_online_list_ip"] = ips;

                // unlock application object 
                Application.UnLock();
            }
            catch {}
        }

        void Session_End(object sender, EventArgs e)
        {
            try
            {
                // lock application object
                Application.Lock();

                // get hashset containing all online ip adresses
                var ips = (HashSet<string>)Application["visitors_online_list_ip"];

                // get user ip from Session because httpcontext doesn't exist
                var ip = Session["ip"].ToString(); ;

                // remove ip from hashset
                ips.Remove(ip);

                // save hashset
                Application["visitors_online_list_ip"] = ips;

                // unlock application object 
                Application.UnLock();
            }
            catch {}
        }
于 2015-01-23T12:47:36.340 回答
0

正如 Hans 提到的,您可能必须将会话状态切换为StateServeror SQLServer,但这不是代码片段可以做到的。关于 codeproject有一篇非常可靠和详细的文章可以正确处理这个问题。

于 2012-07-09T11:04:12.160 回答
0

这是我根据 Hans Kesting 的建议实现的源代码。

全球.asax

void Session_Start(object sender, EventArgs e) 
    {
        System.Collections.Generic.Dictionary<string, DateTime> Visitors =
                            new System.Collections.Generic.Dictionary<string, DateTime>();
        Visitors.Add(Session.SessionID, DateTime.Now);        
        HttpContext.Current.Application.Lock();
        Application["Visitors"] = Visitors;
        HttpContext.Current.Application.UnLock();
    }

HttpHandler.cs

private static void UpdateVisitors()
    {
        System.Collections.Generic.Dictionary<string, DateTime> Visitors = (System.Collections.Generic.Dictionary<string, DateTime>)HttpContext.Current.Application["Visitors"];
        Visitors[HttpContext.Current.Session.SessionID] = DateTime.Now;
    }

AnyPage.aspx.cs(要在哪里获取总在线用户数)

 protected int GetCurrentOnlineUsers()
        {
            int total = 0;
            Dictionary<string, DateTime> Visitors = (Dictionary<string, DateTime>)Application["Visitors"];
            foreach (KeyValuePair<string, DateTime> pair in Visitors)
            {
                TimeSpan Remaining = DateTime.Now - pair.Value;
                int remainingMinutes = Convert.ToInt32(Remaining.TotalMinutes);            
                if (remainingMinutes < 21) //Only count the visitors who have been active less than 20 minutes ago.
                    total++;
            }

            return total;
        }
于 2012-07-11T01:48:06.387 回答