主题:  请高手救命:显示已在线用户问题(ASP.NET代码)

dreamexpress_5d

职务:普通成员
等级:1
金币:10.0
发贴:2229
#12004/9/26 20:52:47
用户表里有一IsLogin字段,当用户登录成功后,将IsLogin设为TRUE。
退出登录时,将将IsLogin设为FALSE。



想通过查询IsLogin为TRUE的用户数量,而显示出登录用户的人数(即在线注册用户的人数)

问题:但是如用户登录后,并没有执行退出登录功能而直接关闭浏览器的话,UserLogOUT()并没有被执行,即用户表中的IsLogin字段一直为TRUE,这怎么办?

============
登录按扭代码:
Private Sub btnLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim CurrentUser As UserInfo
'用Session("CurrentUser")来实例化CurrentUser,此时CurrentUser.Islogin=False
        CurrentUser = DirectCast(Session("CurrentUser"), UserInfo)
'将用户输入的用户名和密码赋给CurrentUser.UserName,CurrentUser.UserPWD属性,准备验证
        CurrentUser.UserName = TextBox1.Text
        CurrentUser.UserPWD = TextBox2.Text
'通过 Userlogin()子程序来验证能否登录,能登录,则CurrentUser.Islogin=TRUE,否则为FALSE(具体请见Userlogin()子程序)
        CurrentUser = Userlogin(CurrentUser)
   
    End Sub


退出登录按钮的代码:
Private Sub btnLogout_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim CurrentUser As UserInfo
'用Session("CurrentUser")来实例化CurrentUser
        CurrentUser = DirectCast(Session("CurrentUser"), UserInfo)
        CurrentUser = UserlogOut(CurrentUser)


    End Sub



登录验证子程序的代码如下:
Public Function Userlogin(ByVal MyUserInfo As UserInfo) As UserInfo
            Dim CurrentUser As New UserInfo

            Dim mySql As String
            mySql = "Select UserID from Employee where UserName='" & MyUserInfo.UserName & "'"
            mySql &= " and UserPWD='" & MyUserInfo.UserPWD & "'"

            ObjSql.strSQL = mySql
            Dim dr As SqlDataReader = ObjSql.SelectFromDBrd()

            If dr.Read Then
                MyUserInfo.IsLogin = True
                MyUserInfo.UserId = dr("UserId")
                dr.Close()
'将用户表中的IsLogin字段改为TRUE(1)(*****重点看看这句*****)
                mySql = "Update Employee set IsLogin=1 where userid='" & MyUserInfo.UserId & "'"
                ObjSql.strSQL = mySql
                ObjSql.ExecuteSQL()

            Else
'用户不能登录。。。。
                MyUserInfo.IsLogin = False
                dr.Close()
            End If
            CurrentUser = MyUserInfo

            Return CurrentUser
end sub


退出登录子程序的代码如下:
 Public Function UserlogOut(ByVal MyUserInfo As UserInfo) As UserInfo
            Dim CurrentUser As New UserInfo
            Dim mySql As String
            If MyUserInfo.IsLogin = True Then
'将用户表中的IsLogin字段改为FALSE(0)(*****重点看看这句*****)
                mySql = "Update Employee set IsLogin=0 where userid='" & MyUserInfo.UserId & "'"
                ObjSql.strSQL = mySql
                ObjSql.ExecuteSQL()
                MyUserInfo.IsLogin = False

                

            End If
            CurrentUser = MyUserInfo
            Return CurrentUser
end sub


这两个子程序均能正常工作。

问题:但是如用户登录后,并没有执行退出登录功能而直接关闭浏览器的话,UserLogOUT()并没有被执行,即用户表中的IsLogin字段一直为TRUE,这怎么办?

将UserLogOUT()放在Session On end 中也不行:
    Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' SESSION开始时,建立一个Session("CurrentUser") 
        Dim CurrentUser As New UserInfo
        Session("CurrentUser") = CurrentUser

    End Sub

Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
        ' 在会话结束时激发

        UserlogOut(DirectCast(Session("CurrentUser"), UserInfo))

    End Sub

编辑历史:[此帖最近一次被 dreamexpress 编辑过(编辑时间:2004-09-26 22:03:57)]


蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#22004/9/26 21:17:35
现在论坛的一般做法是建一在线用户表,其中增加一字段为登录时间。第二个人打开时,就把所有超时的用户删除了。


非常大鱼

dreamexpress_5d

职务:普通成员
等级:1
金币:10.0
发贴:2229
#32004/9/26 21:28:57
超时的用户删除?什么是超时的用户啊?难道以第二个用户登录的时间为准,其前的在线用户均删除(在在线用户表中),我不大明白这是如何能确定出总的在线人数的。

另外:
Session_End怎么好象不起作用呢?难道Session_End事件中不能对数据库进行操作?

是不是用户关掉浏览器时,Session_End事件中的代码来不及执行?

编辑历史:[此帖最近一次被 dreamexpress 编辑过(编辑时间:2004-09-26 21:38:37)]


蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#42004/9/26 21:41:38
没有正常退出很普遍,写程序是比较难判断非正常退出。一般人如果在家上网,都不会选择退出的。没有退出,很可能他没有在浏览网页。所以用时间来判断,比如他5分种内没有刷新或看其它的页面,就应该算他已经下线了。
应该在每个浏览的页面上增加程序,如果他打开这个页面,在线时间应该更新为打开时的时间。比如他最后浏览的时间为10:20分,如果第二个人在10:50打开任何页面,发现该用户时间超过,说明该用户早已下线,就应该把他从在线表中删除。当然可能这个论坛不是很热闹,我打比方的说。


非常大鱼

dreamexpress_5d

职务:普通成员
等级:1
金币:10.0
发贴:2229
#52004/9/26 21:52:39
谢谢蓝鲸的解答。

不过想问一下,我做的这样为何无法实现想要的功能?关键是为什么以下代码在用户直接关闭浏览器时不起作用(即UserlogOut()根本没在Session_End中执行)?????????

难道用户关闭浏览器时,Session_End事件根本不发生?还是来不及执行就结束了??

按我的理解:用户关闭浏览器时,Session_End事件中的代码是应被完全执行的。这个概念难道有错????????
Sub Session_End(ByVal sender As Object, ByVal e As EventArgs)
        ' 在会话结束时激发

        UserlogOut(DirectCast(Session("CurrentUser"), UserInfo))

    End Sub



dreamexpress_5d

职务:普通成员
等级:1
金币:10.0
发贴:2229
#62004/9/26 22:28:23
难道是Session变量先变的无效,然后再执行Session_End事件?

不过我直接在Session_End给出一个明确的用户(而不是从SESSION变量中取用户),好象也不行啊。在用户直接关闭浏览器时,UserlogOut()还是没执行。晕~~~~~~



蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#72004/9/26 22:59:12
Session关闭与Session.TimeOut设置时间有关,默认20分钟。
如果用Session.Abandon();也不会马上停止Session。
晚上我对ASPX测试,

在Application_Start使
Application["Test"] = "Start";

在ASPX文件中的Load中
TextBox1.Text = Application["Test"].ToString();
Application["Test"] = "End";
Session.Abandon();

在Session_End中
Application["Test"] = "ISEnd";

第一次启动页面,文本框中显示"start",第二次显示"End",而不是所希望的"IsEnd",
说明关闭页面对Session_End不起作用。


非常大鱼

蓝鲸

职务:版主
等级:5
金币:42.1
发贴:2614
#82004/9/26 23:07:54
Session是写在IIS里的,与Cookie不同。
如果一定要这样,可以在页面的UnLoad事件中看看。但也不保险,你没法控制如死机,掉电等情况。所以用时间来判断是比较保险的。


非常大鱼

dreamexpress_5d

职务:普通成员
等级:1
金币:10.0
发贴:2229
#92004/9/27 10:18:03
页面的UnLoad事件只表示用户关闭了该页,并不能保证登录用户不在线啊,我想要的是用户关闭所有的浏览窗口时才更新用户的在线状态,而不是用户关了某页(可能它还在看网站的其它页,此时仍在线)。



dreamexpress_5d

职务:普通成员
等级:1
金币:10.0
发贴:2229
#102004/9/27 10:23:02
蓝鲸在上个帖子中说
引用:
Session关闭与Session.TimeOut设置时间有关,默认20分钟。
如果用Session.Abandon();也不会马上停止Session。
晚上我对ASPX测试,

在Application_Start使
Application["Test"] = "Start";

在ASPX文件中的Load中
TextBox1.Text = Application["Test"].ToString();
Application["Test"] = "End";
Session.Abandon();

在Session_End中
Application["Test"] = "ISEnd";

第一次启动页面,文本框中显示"start",第二次显示"End",而不是所希望的"IsEnd",
说明关闭页面对Session_End不起作用。


确实如此,我也测试了Application("N")+=1和Application("N") -=1的情况,不行。Session_End中的语句根本就起不了作用。这是何故???难道我在Session_End的概念认识上就不对?

编辑历史:[此帖最近一次被 dreamexpress 编辑过(编辑时间:2004-09-27 10:31:51)]