1. 程式人生 > >【ASP.NET】——統計線上人數、歷史訪問人數

【ASP.NET】——統計線上人數、歷史訪問人數

    北大青鳥的視訊中講了很多很實用的例子,這是其中一個,在實現的過程中,遇到一些問題,但也都在老師的指導下和通過查閱資料解決了,感覺收穫頗豐。

    在做這個例子的時候發現:ASP.NET的Application和Session統計線上人數和歷史訪問人數時不準。明明已經關閉瀏覽器了,線上人數卻沒少,重新登入,歷史人數也沒增加。難道是我做錯了,No.原因在這裡。

    首先,先簡單說一下Application和Session。    

    Application:應用程式類的物件。類比到這個程式,伺服器端的統計人數程式就相當於一個Application,而使用者與之建立的連線則相當於一個Session。

    由此,能理解到:Application是共享的,相當於全域性變數,Session則是會話級的,相當私有變數。

    借用師哥的一張圖代表他們的關係就是:

類比出:


    當程式啟動時,首先執行Application_Start()事件:這裡有兩個兩個變數:total用於記錄歷史人數,online用於記錄線上人數。

<span style="font-family:KaiTi_GB2312;font-size:24px;"> protected void Application_Start(object sender, EventArgs e)
        {
            SqlConnection con = new SqlConnection("server=.;database=countPeople;uid=sa;pwd=123456;");
            con.Open();
            SqlCommand cmd = new SqlCommand("select * from countPeople", con);
            int count = Convert.ToInt32(cmd.ExecuteScalar());
            con.Close();

            Application["total"] = count;
            Application["online"] = 0;
        }</span>

    繼而,當用戶登入時,會觸發Session_Start()事件。讓兩變數+1。這裡還加了一個鎖,是為了防止併發訪問而導致錯誤。加鎖後:Application的Lock()方法先把Application中的變數鎖起來(Application執行了Lock()方法之後,整站中所有關於Application的操作都會被鎖定延時執行,包括Application賦值和Application讀取),只讓一個客戶端進行這兩個變數的自增,之後再進行解鎖,供其他客戶端進行操作:

<span style="font-family:KaiTi_GB2312;font-size:24px;"> protected void Session_Start(object sender, EventArgs e)//進行連線
        {
            Session.Timeout = 1;
            Application.Lock();//加鎖:防併發
            Application["total"] = (int)Application["total"] + 1;    //歷史人數+1
            Application ["online"]=(int)Application ["online"]+1;    //線上人數+1
            Application .UnLock();//解鎖
        }</span>
    至此,歷史人數和線上人數都更新在變數中了,需要的時候呼叫即可。

    當一個客戶端下線的時候,會觸發Session_End()事件,這時,線上人數-1。

<span style="font-family:KaiTi_GB2312;font-size:24px;"> protected void Session_End(object sender, EventArgs e)//斷開連線
        {
            Application.Lock();
            Application["online"] = (int)Application["online"] - 1;
            Application.UnLock();
        }</span>
    做過這個例子的同學應該遇到過:開啟兩個客戶端,即建立兩個Session,線上人數為2,關閉其中一個,重新整理另一個,結果線上人數還是2。
    這是因為Session中有個預設的Timeout=20。即預設情況下,關閉了瀏覽器並不代表這個瀏覽器和伺服器之間的連線已經斷開,而要等待20分鐘之後才會斷開連線。(為了測試效果,您可以將TimeOut的值設定小一點,最小為1)。Timeout還有一個這樣的作用:當客戶端在timeout設定時間內沒有任何響應,也當下線處理,即線上人數減1,以減少無必要的資源佔用。

    最後,關閉程式,Application中儲存的歷史訪問資料存入資料庫。

<span style="font-family:KaiTi_GB2312;font-size:24px;"> protected void Application_End(object sender, EventArgs e)
        {
            SqlConnection con = new SqlConnection("server=.;database=countPeople;uid=sa;pwd=123456;");
            con.Open();
            SqlCommand cmd = new SqlCommand("update countPeople set num="+Application["total"].ToString(),con);
            cmd.ExecuteNonQuery();
            con.Close();

        }</span>
    但結束執行後,會發現,資料庫中並沒有增加的資料,這說明關閉系統時沒有觸發Application_End()這個事件。那該怎麼做呢?

    首先,得把程式釋出,以IIS為例:當想觸發Application_End()時,需要在IIS中關閉此程式的執行。重啟和強行關閉都不會觸發該事件。


    除此方法可以觸發Application_End()外,正常關機可以觸發,正常關機時,Web應用程式關閉,歷史記錄更新。而Web關閉時,關的是:控制面板\系統和安全\管理工具\服務:world wide web publishing service,所以,為了開著機看效果,我們可以手動關閉該項,以此來更新資料庫。

    總結:

    這是一個很實用的例子,今後應該會經常遇到。通過這個例子,瞭解了Application和Session的區別,聯絡......也通過這個例子,學會了不斷嘗試,再嘗試中尋找並驗證答案......