Web功能(C#) - 線上人數 & 累計人數

運用Global.asax來寫網頁的線上人數功能,並且連線資料庫取出累計人數計算,使用到全域變數Application和Session物件。

修改於:https://goo.gl/FlR7a5

 

我的檔案總管,主要是以下選起來的程式在運作

畫面結果

SQL Server內容

 

------------------ Global.asax ----------------------

<%@ Application Language="C#" %>
<%@ Import Namespace="WebSite8" %>
<%@ Import Namespace="System.Web.Optimization" %>
<%@ Import Namespace="System.Web.Routing" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script runat="server">

    long CounterUser = 0;
    long HisCounterUser = 0;
    long hisuser = 0;
    //建立資料庫連線
    SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=myDB;User Id=sa;Password=密碼");
    SqlCommand cmd = null;
    
    void Application_Start(object sender, EventArgs e)
    {
        
    }

    void Session_Start(object sender, EventArgs e)
    {
        //取出資料庫歷史訪問人數
        string sSql = "select CountUser from CountTable";
        conn.Open();
        cmd = new SqlCommand(sSql, conn);
        //執行此SQL查詢
        SqlDataReader dr = cmd.ExecuteReader();
        while (dr.Read())
        {
            hisuser = Convert.ToInt64(dr.GetString(0));
            Application.Set("HisTotalUsers", hisuser);
        }
        conn.Close();
        
        ArrayList arrltTemp = new ArrayList();
        string strUserID = null; //用戶識別碼
        string strUserSessionID = Session.SessionID; //取得進入頁面後系統給予的 Session 唯一識別碼
        int intNum = 0; //人數計數器
        int i = 0;
        int intCheckTickSeconds = 30; //用戶最後存取時間以秒計算
        Session["Flag"] = true; //新增此 Session 變數以使 Session 物件能正常運作
        DateTime dtDateTime = DateTime.Now; //取得目前時間

        Application.Lock();

        //Application 名稱全域變數為空值時,代表該用戶為第一次進入
        if (Application[strUserSessionID + "LastAccessTime_A"] == null)
        {
            //設定預設值
            if (Application["TotalUsers_A"] == null)
            {
                //所有線上用戶數量為0
                Application.Set("TotalUsers_A", 0);
            }

            //取得 Application 的"線上用戶名單"陣列
            ArrayList arrltOnlineUserC = (ArrayList)Application["OnlineUser_A"];
            //設定累計數值值為 0
            intNum = 0;

            if ((int)Application["TotalUsers_A"] > 0) //線上已經有人進入,不是第一次進來的狀況
            {
                if (arrltOnlineUserC != null)
                {
                    //讀取「線上用戶名單」陣列範圍,將「新加入用戶」與 
                    //「舊有存在用戶」陣列內容做比較看是否以經存在。

                    //利用「元素長度」取得一維陣列內容值。(線上用戶名單)
                    for (i = 0; i < arrltOnlineUserC.Count; i++)
                    {
                        //取出存放在「舊有存在用戶」陣列裡面的用戶名單。
                        strUserID = arrltOnlineUserC[i].ToString();
                        //當「舊有存在用戶」不等於「新加入用戶」陣列名單時。
                        if (strUserID != strUserSessionID.ToString())
                        {
                            //將「舊有存在用戶」放入陣列項目裡面。
                            arrltTemp.Add(strUserID);
                            //累加計數值。(統計人數)
                            intNum += 1;
                        }
                    }
                }
            }

            //將「新加入的用戶」放入「舊有存在用戶」陣列項目裡面。(此陣列位置為最後一筆)
            arrltTemp.Add(strUserSessionID);
            Application.Set("TotalUsers_A", intNum + 1); //線上所有人數累加
            Application.Set("HisTotalUsers", hisuser + 1); //累加歷史訪問人數
            //將之前清查的陣列項目值「目前用戶名單」放入 Application「線上用戶名單」值裡面。
            Application.Set("OnlineUser_A", arrltTemp);
        }

        //指派目前進入用戶的「Session 個人變數 ID 和最後存取時間」Application 名稱全域變數值。(目前存取時間)
        Application.Set(strUserSessionID + "LastAccessTime_A", DateTime.Now.ToString());

        //== 檢查所有連線到此網頁之瀏覽器的最近存取時間,重新計算線上人數名單。
        //== 如果與目前時間相差30秒以上,表示結束連線。

        //使用動態陣列讀取。(取得 Application 的「線上用戶名單」陣列)
        ArrayList arrltOnlineUserT = (ArrayList)Application["OnlineUser_A"];
        //指派累加值為0。
        intNum = 0;

        //宣告日期物件操作案例。
        DateTime dtLastAccessTime = new DateTime();

        //讀取「線上用戶名單」陣列項目。
        for (i = 0; i < arrltOnlineUserT.Count; i++)
        {
            //當 Application 全域變數「用戶最後存取時間」不是無值時。
            if (Application[arrltOnlineUserT[i].ToString() + "LastAccessTime_A"] != null)
            {
                //取得 Application 全域變數的「用戶最後存取時間」。
                dtLastAccessTime = DateTime.Parse(Application[arrltOnlineUserT[i].ToString() + "LastAccessTime_A"].ToString());
                //宣告刻度間隔物件操作案例。(取得「目前時間」與「用戶最後存取時間」相差距的秒數)
                TimeSpan tsTicks = new TimeSpan(dtDateTime.Ticks - dtLastAccessTime.Ticks);
                //當相差距的秒數小於 30 秒時。
                if (Convert.ToInt32(tsTicks.TotalSeconds) < intCheckTickSeconds)
                {
                    //累加計數值。(統計人數)
                    intNum += 1;
                }
                else //當相差距的秒數大於 30 秒時。
                {
                    //設定目前用戶的「用戶最後存取時間」Application 變數為無值。(清除 Application)
                    Application.Set(arrltOnlineUserT[i].ToString() + "LastAccessTime_A", null);
                    Application.Set(arrltOnlineUserT[i].ToString(), null);
                    Application.Remove(arrltOnlineUserT[i].ToString() + "LastAccessTime_A");
                    Application.Remove(arrltOnlineUserT[i].ToString());
                }
            }
        }

        //當上面所清查完成的「目前線上人數」與 Application「線上所有人數」不同就表示中間有人斷線。
        if (intNum != (int)Application["TotalUsers_A"])
        {
            //將陣列項目值「線上用戶名單」放入 Application["OnlineUser_A"] 全域陣列值裡面。
            Application.Set("OnlineUser_A", arrltOnlineUserT);
            //將上面所清查的「線上人數」放入 Application["TotalUsers_A"] 全域變數裡面。
            Application.Set("TotalUsers_A", intNum);
        }

        //輸出線上總人數
        //CounterUser = Convert.ToInt64(Application["TotalUsers_A"]);
        //輸出歷史訪問人數
        //HisCounterUser = Convert.ToInt64(Application["HisTotalUsers"]);

        Application.UnLock();

        //Label8.Text = CounterUser.ToString();
        //Label10.Text = HisCounterUser.ToString();

        //將歷史人數寫回資料庫
        try
        {
            //更新
            string sSql2 = "Update CountTable Set CountUser='" + Application["HisTotalUsers"] + "' ";
            conn.Open();
            cmd = new SqlCommand(sSql2, conn);
            cmd.ExecuteNonQuery();
        }

        catch (Exception ex)
        {
            Application["Msg"] = ex.ToString();
        }
        finally
        {
            cmd.Dispose();
            conn.Close();
            conn.Dispose();
        }
    }

    void Session_End(object sender, EventArgs e)
    {
        
    }
    
    void Application_End(object sender, EventArgs e)
    {
        //  應用程式關閉時執行的程式碼

    }

    void Application_Error(object sender, EventArgs e)
    {
        // 發生未處理錯誤時執行的程式碼

    }

</script>

----------------------- Default.aspx -----------------------------

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<asp:Content runat="server" ID="FeaturedContent" ContentPlaceHolderID="FeaturedContent">
    <section class="featured">
        <div class="content-wrapper">
            <hgroup class="title">
                <h1><%: Title %>.</h1>
                <h2>Modify this template to jump-start your ASP.NET application.</h2>
            </hgroup>
            <p>
                累計人數:<%= Application["HisTotalUsers"]%></p>
            <p>
                縣上人數:<%= Application["TotalUsers_A"]%></p>
            <p>
                <%= Application["Msg"]%></p>
        </div>
    </section>
</asp:Content>