轉載自:http://www.tuicool.com/articles/qyE3e2a
先來簡單說一下ASP.NET中的Application和Session
下圖是我們非常熟悉的Web應用程序的結構:
在這張圖中,Web服務器中運行的Web應用程序就是我們所說的Application,每個客戶端與Web服務器之間建立的連接就可以看做是一個Session。比如現在服務器端運行的是一個論壇系統,那么現在這個正運行在服務器端的論壇系統的軟件就可以看做Application,而每個在線的用戶與之建立的連接就相當於一個Session。
那么很容易就會理解,Application是共享的,相當於“全局變量”,Session不是共享的,是屬於每個客戶端(瀏覽器)私有的。
所以上圖用Application和Session 可以 表示為:
Application
常用屬性:
屬性 | 說明 |
All | 返回全部的Application對象變量到一個對象數組 |
AllKeys | 返回全部的Application對象變量到一個字符串數組 |
Count | 返回Application中對象變量的數量 |
常用方法:
方法 | 說明 |
Add | 新增一個Application變量值 |
Clear | 清空全部Application變量值 |
Get | 變量名傳回的變量值 |
Set | 更新Application變量值 |
Lock | 鎖定所有Application的變量值 |
UnLock | 解除鎖定Application的變量值 |
Session
常用屬性:
屬性 | 說明 |
Count | 獲取會話狀態集合中Session對象的個數 |
Contents | 獲取對當前會話狀態對象的引用 |
Keys | 獲取存儲在會話中的所有值的集合 |
SessionID | 獲取用於標識會話的唯一會話ID |
TimeOut | 獲取或設置會話狀態提供程序終止會話之前所允許的超時期限 |
Mode | 獲取當前會話狀態模式 |
常用方法:
方法 | 說明 |
Add | 新增一個Session對象 |
Clear | 清除會話狀態中的所有值 |
CopyTo | 將會話狀態值的集合富之島一維數組中 |
Remove | 刪除會話狀態集合中的項 |
RemoveAll | 清除所有會話狀態的值 |
ASP.NET中統計在線人數和歷史訪問人數,還需要四個事件:Application_Start()事件、Application_End()、Session_Start()事件和Session_End()事件。
當程序啟動時,會首先在Global.asax.cs文件中觸發Application的Application_Start()事件,我們需要在這個事件中增加兩個Application變量值(因為這兩個值是Application中的變量值,所以就相當於整個程序的“公共變量”):totalCount(用來表示總的訪問量)、onlineCount(用來表示當前在線人數):
protected void Application_Start() { string strConn = "server=192.168.24.123;database=數據庫名;uid=sa;pwd=123456;"; //數據庫連接字符串 SqlConnection conn = new SqlConnection(strConn); //實例化數據庫連接對象 conn.Open(); //打開數據庫連接 string cmdText = "select count from Count"; //定義查詢字符串 SqlCommand cmd = new SqlCommand(cmdText, conn); //實例化命令對象 int count = (int)cmd.ExecuteScalar(); //取出數據庫中歷史訪問人數 Application["total"] = count; //定義Application變量值total並賦值為歷史訪問量 Application["onLine"] = 0; //定義Application變量值onLine並賦值為0 }
下面就要編寫Session_Start()事件代碼,當每個客戶端(瀏覽器)訪問服務器時,就會觸發Session_Start()事件,這事就要讓“公共變量”totalCount和onlineCount都自增1,這時,當有多個客戶端同時訪問時,就有可能發生錯誤,所以要Application的Lock()方法先把Application中的變量鎖起來(Application執行了Lock()方法之后, 整站中所有關於Application的操作都會被鎖定延時執行,包括Application賦值和Application讀取),只讓一個客戶端進行這兩個變量的自增,之后再進行解鎖,供其他客戶端進行操作:
protected void Session_Start() { Application.Lock(); //鎖定Application Application["total"] = (int)Application["total"] + 1; //總訪問量加1 Application["onLine"] = (int)Application["onLine"] + 1; //在線人數加1 Application.UnLock(); //解除鎖定 }
現在在線人數和歷史訪問數量都統計出來了,需要顯示的時候直接調用Application["變量值"]就可以,比如要在名為Label的控件上顯示在線人數,只需Label.Text=Application["onLine"].ToString()就OK了!需要 注意 的是,Application和Session中存儲的變量值都是object類型的,給他們賦值的時候可以直接賦值,但是取出的時候就需要考慮類型了。
當一個客戶端(瀏覽器)與服務器斷開連接(即此客戶端與服務器的會話關閉)時,會觸發Session_End()事件,這時歷史訪問數量不改變,在線人數需要減1:
protected void Session_End() { Application.Lock(); //鎖定Application Application["onLine"] = (int)Application["onLine"] - 1; //總訪問數量不變,在線人數減1 Application.UnLock(); //解除鎖定 }
為了方便測試,上面的例子可以通過在一台電腦上開啟多個瀏覽器,也就相當於與服務器建立了多個Session,也許您測試的時候會發現一個問題,假如現在在線人數是10,您關閉了某個瀏覽器時,測試當前的在線人數即Application["onLine"]的值還是10 ,並沒有執行“減1”操作。這是因為Session的TimeOut值默認是20分鍾,也就是說,默認情況下,關閉了瀏覽器並不代表這個瀏覽器和服務器之間的連接已經斷開,而要等待20分鍾之后才會斷開連接。(為了測試效果,您可以將TimeOut的值設置小一點)
最后,假如服務器要關閉,就要把目前Application中存儲的歷史訪問總數重新更新到數據庫中,需要在Application_End()事件中進行:
protected void Application_End() { string strConn = "server=192.168.24.123;database=數據庫名;uid=sa;pwd=123456;"; //定義數據庫連接字符串 SqlConnection conn = new SqlConnection(strConn); //實例化數據庫連接對象 conn.Open(); //打開數據庫連接 string cmdText = "update Count set count=@count"; //定義執行命令 SqlCommand cmd = new SqlCommand(cmdText, conn); //實例化命令對象 cmd.Parameters.Add(new SqlParameter("@count", Application["total"])); //為參數@count賦值為現在的總訪問量 cmd.ExecuteNonQuery(); //執行命令 conn.Close(); //關閉數據庫 }
通常在整個過程中,大多數人對Application_End()這個事件的疑問是最大的,因為如果您只是在VisualStudio上做的測試的話,關閉系統時,沒有觸發Application_End()事件,新的數據也就沒有被寫入到數據庫中。那么Application_End()究竟在什么時候才會被觸發呢 ?
想弄明白這個問題,需要將程序發布,這里以IIS為例,用IIS發布了程序之后運行,當想要觸發Application_End()事件把最新的歷史訪問量寫入到 數據庫中時,需要在IIS中關閉此程序的運行,如下圖:
注意 :只是在服務器上停止該程序的運行才會觸發Application_End()事件,重啟和斷電等情況並不能觸發。
雖然統計在線人數和歷史訪問量是個並不起眼的小功能,但是通過捋一遍,細細地總結了一下,又學到了好多東西,腦子里的知識網又增大了一點點。。。。