声明:本文内容纯属个人观点,官方保留最终解释

     在上文(Discuz!NT URL地址重写) 中, 聊到了“在线用户”功能,因为当时介绍的重点不是“在线”
那一块,所以没做深入介绍。这就为今天这篇文章埋下了“伏笔”。因为在线这个功能太重要了,大家不妨
用VS打开我们产品的最新源码,然后搜索一下“OnlineUsers.”这个内容就会看到它在产品中被使用的“频
率”。
 
     好了,言归正传,下面就开始接着上一篇文章中所说的“OnlineUsers.ResetOnlineList();” 方法介绍
一下用户在线功能。

     首先请大家打开Discuz.Forum这个项目,从中找到"OnlineUsers.cs"这个文件,打开它找到
"ResetOnlineList()"这个函数,它的代码如下:

   

 1

      这个函数本身就是在系统启动之后的10分钟内运行InitOnlineList函数,而为什么是10分钟(
不是别的时间段呢?),主要是因为这个值是个“估计值”,因为在线功能是系统的核心功能之一,
换句话说,系统在启动10分钟内,只要是用户在前台进行操作,绝对会用到这个核心功能,而这个
功能本身是依赖于数据库中的“dnt_onlines"表的(如果大家想了解这个表的结构,可以下载我们
产品的“数据字典”,里面有这方面内容的介绍)。所以创建(复位)和初始化这个数据表的责任就
交给了ResetOnlineList()这个函数(因为它是在HttpModule.cs中被绑定的,可以看作是系统运行
的起点,详情见上文)。

     好了,即然清楚了这个函数的作用,不妨再了解一下代码中InitOnlineList()方法,它的作用
就是运行下面这个SQL语句:

 

 1Discuz!NT 在线用户功能简介//该函数位于Discuz.Data.SqlServer项目中的UserManage.cs文件中
 2Discuz!NT 在线用户功能简介 public int CreateOnlineTable() 
 3

     该方法如果正常运行的话,会在数据库中建立dnt_onlines"这个表。用于记录在线用户的全部
信息。


     上文介绍的仅仅是系统“初始化”时所要做的“活”。而更重要的内容是用户从一访问论坛并
执行一系列操作(如登陆,发贴,浏览版块等)时,“在线用户”机制在里面所启的重要作用。

     这里先以登陆(系统)这一操作发生时,程序所做出的响应为例,看一下在线这块是如何进行绑
定的,请看如下代码(位于discuz.web项目的“aspx/1/”文件夹下的login.aspx.cs文件):
     
    

1Discuz!NT 在线用户功能简介Discuz!NT 在线用户功能简介Discuz!NT 在线用户功能简介
2Discuz!NT 在线用户功能简介    OnlineUsers.UpdateAction(olid, UserAction.Login.ActionID, 0, config.Onlinetimeout);
3Discuz!NT 在线用户功能简介    Discuz!NT 在线用户功能简介Discuz!NT 在线用户功能简介
4Discuz!NT 在线用户功能简介

    它的作用就是将已成功登陆系统的用户所执行的当前动作及相关信息更新到"dnt_onlines" 表
中。而这个函数本身所用到的四个参数要重点介绍一下:

     olid: 在线列表id,对应"dnt_onlines"表中的olid字段

     action:动作(结构类型,详情参见discuz.forum项目下的forumutils.cs文件)
           用于传递动作的相关信息如:ActionName动作名称和ActionDescription动作描述等)

     inid: 所在位置代码,即当前用户所访问的主题(TopicId)。因为登陆不牵扯主题操作,所
           以上面的值为0

     timeout: 无动作离线时间(config.Onlinetimeout),这个数据是在后台进行设置的,见下图:

 Discuz!NT 在线用户功能简介

      timeout的作用就是当有别人访问论坛时,在更新自身在线状态信息同时,用这个设置数据(
整型)与在线表(dnt_onlines)中的"lastupdatetime"字段(最后活动时间)进行比较,找出超过
timeout规定的时间的用户,将其在线状态(onlinestate)设置为0(即为离线)。而做这件事的函
数就是在项目“discuz.data.sqlserver”下的“UserManage.cs”中的“AddOnlineUser”函数,这
里将它的代码贴出来,详情见注释:

        

 1

      需要说明一下,就是在线表的删除问题。因为这个在线表是通过程序在数据库中进行创建的,
同时表中的olid又是一个自增字段(标识自增为1),因此为了避免自增字段最终超过最大值范围
(因为在线表经常有数据添加进来)。所以在上面加入了"olid > 2147483000"的逻辑判断,来预
防这个问题的出现。

      说了一大堆的关于timeout参数的问题,而另一个重要的参数olid还没作详细介绍呢:)

     上面所述的登陆页面(login.aspx.cs)中,olid是从basepage类中获得的,而basepage就是前
台主要页面的“基类”,它里面的构造函数部分封装了页面中大部分公共变量的初始化操作。所以要
了解olid,还要从basepage.cs中分析一把。

    请看下面的代码段(摘自discuz.web.ui项目下的basepage.cs文件):

    

 1

     从代码中可以看出olid是通过louserinfo对象进行赋值的,而louserinfo对象是通过UpdateInfo
来进行实始化绑定的,所以我们还需要再看一下这个函数,相关代码段如下:

   

 1

      看到这里大家明白了吧,原来不管用户是否注册登陆,这个函数都会将一些信息更新或添加到在线
表中。即判断当前用户的身份(会员还是游客),是否在"在线列表"中存在,如果存在则更新会员的当前动作,
不存在(首次访问)则初始化相关(游客)用户信息。

      下面再介绍一下action这个参数,它是结构(struct)类型,里面的ActionName动作名称和ActionD-
escription动作描述(目前未用上)是用于显示当前动作信息的。相应的显示效果如下图所示:

      Discuz!NT 在线用户功能简介

     
     
      如果大家觉得没问题的话,下面再介绍一下注销(退出)操作,因为有登陆就会有退出。而注销这
块的操作也很简单,请看如下代码段(位于aspx/1/logout.aspx.cs文件):
    

 1Discuz!NT 在线用户功能简介public class logout : BasePage
 2

    
    代码中的userkey其实是一个用户password的一个子串(详情上面basepage.cs代码中的相应部分)。
    而“OnlineUsers.DeleteRows(olid);”这行代码其实就是删除在线表中指定olid的用户信息了。因
为代码过于简单,只是一条SQL语句而已,所以就不在这里多费笔默了。

    其实关于在线表有关的操作还有很多,大家不妨挖一下onlines.cs这个文件,从中会有更多的收获。

    最后再介绍一下有关“最大在线人数”这个问题,其实这个功能主要是为了中小站长(服务器资源相
对紧张)提供的一项设置,旨在当用户在线人数达到一定数量时,拒绝其它的访问。相应的代码判断逻
辑如下(摘自basepage.cs文件):

   

 1Discuz!NT 在线用户功能简介 if (config.Onlinetimeout > 0 && userid != -1)
 2

     里面的GetOnlineAllUserCount()和GetCacheOnlineAllUserCount()均为返回在线人数的方法,而
config.Onlinetimeout的设置是在管理后台完成的,见下图:

 Discuz!NT 在线用户功能简介

     好了,今天的文章就先写到这里了,希望大家不要感觉是在“云里雾里”的:),如果有问题欢迎
与我交流或去我们的官方站点(http://nt.discuz.net)反映问题。

    我的email:  daizhj@discuz.com,  daizhj617595@126.com, daizhj@gmail.com

    关键字:.net,discuz,disucznt,online,在线,在线用户

    作者:代震军,daizhj

    

 


 

相关文章:

  • 2021-08-25
  • 2021-07-01
  • 2022-12-23
  • 2022-12-23
  • 2021-12-27
  • 2021-10-28
  • 2021-07-25
  • 2022-01-08
猜你喜欢
  • 2021-05-16
  • 2022-01-15
  • 2021-08-16
  • 2022-12-23
  • 2021-09-29
  • 2022-12-23
  • 2021-06-25
相关资源
相似解决方案