【ASP.NET】——统计在线人数、历史访问人数



    北大青鸟的视频中讲了很多很实用的例子,这是其中一个,在实现的过程中,遇到一些问题,但也都在老师的指导下和通过查阅资料解决了,感觉收获颇丰。

    在做这个例子的时候发现:ASP.NET的Application和Session统计在线人数和历史访问人数时不准。明明已经关闭浏览器了,在线人数却没少,重新登录,历史人数也没增加。难道是我做错了,No.原因在这里。

    首先,先简单说一下Application和Session。    

    Application:应用程序类的对象。类比到这个程序,服务器端的统计人数程序就相当于一个Application,而用户与之建立的连接则相当于一个Session。

    由此,能理解到:Application是共享的,相当于全局变量,Session则是会话级的,相当私有变量。

    借用师哥的一张图代表他们的关系就是:

【ASP.NET】——统计在线人数、历史访问人数_第1张图片

类比出:

【ASP.NET】——统计在线人数、历史访问人数_第2张图片

    

    当程序启动时,首先执行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中关闭此程序的运行。重启和强行关闭都不会触发该事件。

【ASP.NET】——统计在线人数、历史访问人数_第3张图片
    除此方法可以触发Application_End()外,正常关机可以触发,正常关机时,Web应用程序关闭,历史记录更新。而Web关闭时,关的是:控制面板\系统和安全\管理工具\服务:world wide web publishing service,所以,为了开着机看效果,我们可以手动关闭该项,以此来更新数据库。

    总结:

    这是一个很实用的例子,今后应该会经常遇到。通过这个例子,了解了Application和Session的区别,联系......也通过这个例子,学会了不断尝试,再尝试中寻找并验证答案......

    
    




你可能感兴趣的:(session,application,asp.net)