dz论坛在线时间更新机理分析(解决在线时间不更新和部分用户刷在线时间的问题)

最近在论坛上出现了许多站点的用户在线时间,或者在线用户的列表出现错误数据。针对以上现象,我简单介绍下论坛更新在线时间和在线用户的机理。

所有的操作都在模板文件footer.htm中的一个不起眼的一条语句<!--{eval updatesession();}-->
<!--{eval updatesession();}-->调用的是function_core.php中的updatesession函数。
  1. function updatesession($force = false) {

  2.     global $_G;
  3.     static $updated = false;

  4.     if(!$updated) {
  5.         if($_G['uid']) {
  6.             if($_G['cookie']['ulastactivity']) {
  7.                 $ulastactivity = authcode($_G['cookie']['ulastactivity'], 'DECODE');
  8.             } else {
  9.                 $ulastactivity = getuserprofile('lastactivity');
  10.                 dsetcookie('ulastactivity', authcode($ulastactivity, 'ENCODE'), 31536000);
  11.             }
  12.         }
  13.         $discuz = & discuz_core::instance();
  14.         $oltimespan = $_G['setting']['oltimespan'];
  15.         $lastolupdate = $discuz->session->var['lastolupdate'];
复制代码
$oltimespan = $_G['setting']['oltimespan'];对应的值是后台全局--站点功能--其他--用户在线时间更新时长(分钟)的值。
  1.          if($_G['uid'] && $oltimespan && TIMESTAMP - ($lastolupdate ? $lastolupdate : $ulastactivity) > $oltimespan * 60) {
  2.             DB::query("UPDATE ".DB::table('common_onlinetime')."
  3.                 SET total=total+'$oltimespan', thismonth=thismonth+'$oltimespan', lastupdate='" . TIMESTAMP . "'
  4.                 WHERE uid='{$_G['uid']}'");
  5.             if(!DB::affected_rows()) {
  6.                 DB::insert('common_onlinetime', array(
  7.                     'uid' => $_G['uid'],
  8.                     'thismonth' => $oltimespan,
  9.                     'total' => $oltimespan,
  10.                     'lastupdate' => TIMESTAMP,
  11.                 ));
  12.             }
  13.             $discuz->session->set('lastolupdate', TIMESTAMP);
  14.         }
复制代码
如果是会员登录论坛,判断最近更新时间与当前时间的差大于用户在线时间更新时长时,会更新common_onlinetime表(记录会员在线时间)里对应用户的对应字段的值,若没有对应用户,则添加一条记录。
  1.        foreach($discuz->session->var as $k => $v) {
  2.             if(isset($_G['member'][$k]) && $k != 'lastactivity') {
  3.                 $discuz->session->set($k, $_G['member'][$k]);
  4.             }
  5.         }

  6.         foreach($_G['action'] as $k => $v) {
  7.             $discuz->session->set($k, $v);
  8.         }

  9.         $discuz->session->update();

  10.         $updated = true;
复制代码
然后程序开始更新session(针对所有用户,包括未登录的游客),将session数据存到common_session表里。
  1. if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) {
  2.             if($oltimespan && TIMESTAMP - $ulastactivity > 43200) {
  3.                 $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
  4.                 DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1);
  5.             }
  6.             dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000);
  7.             DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
  8.         }
  9.     }
  10.     return $updated;
  11. }
复制代码
最后根据用户最近的更新的时间,将计算出的用户在线时间,更新到common_member_count表(统计用户记录信息表)里,我们看到的在线时间就是从此表里读取出来的,并且记录当前时间为用户最近活跃的时间。(注意:common_member_count表中的在线时间是每12个小时更新一次)

以上有两个关键点:
在线时间的统计是由该函数执行和保存的,在线会员显示是直接读取的common_session表中的数据

此问题已得到解决.论坛每15分钟统计一次论坛在线情况.如仍有用户出现此问题请在本帖后跟帖描述您的具体情况,我们会在第一时间给予解决.
程序是每15分钟更新一次数据库也就是说.当您登陆论坛时 程序在您登陆之的前一分钟更新过SESSION 缓存,那么您在接下来的13分钟内都会显示离线,直至第二次程序再次运行更新SESSION此时,您的状态会显示在线!
PS: 只开着网页没有进行任何操作是不会更新在线时间的.因为SESSION存在生命周期!


另外,请不再次发帖子说自己的时间不正确,请您理解在线时间更新原理.

转载http://bbs.cnliti.com/thread-75557-1-1.html

最近在论坛上出现了许多站点的用户在线时间,或者在线用户的列表出现错误数据。针对以上现象,我简单介绍下论坛更新在线时间和在线用户的机理。

所有的操作都在模板文件footer.htm中的一个不起眼的一条语句<!--{eval updatesession();}-->
<!--{eval updatesession();}-->调用的是function_core.php中的updatesession函数。
  1. function updatesession($force = false) {

  2.     global $_G;
  3.     static $updated = false;

  4.     if(!$updated) {
  5.         if($_G['uid']) {
  6.             if($_G['cookie']['ulastactivity']) {
  7.                 $ulastactivity = authcode($_G['cookie']['ulastactivity'], 'DECODE');
  8.             } else {
  9.                 $ulastactivity = getuserprofile('lastactivity');
  10.                 dsetcookie('ulastactivity', authcode($ulastactivity, 'ENCODE'), 31536000);
  11.             }
  12.         }
  13.         $discuz = & discuz_core::instance();
  14.         $oltimespan = $_G['setting']['oltimespan'];
  15.         $lastolupdate = $discuz->session->var['lastolupdate'];
复制代码
$oltimespan = $_G['setting']['oltimespan'];对应的值是后台全局--站点功能--其他--用户在线时间更新时长(分钟)的值。
  1.          if($_G['uid'] && $oltimespan && TIMESTAMP - ($lastolupdate ? $lastolupdate : $ulastactivity) > $oltimespan * 60) {
  2.             DB::query("UPDATE ".DB::table('common_onlinetime')."
  3.                 SET total=total+'$oltimespan', thismonth=thismonth+'$oltimespan', lastupdate='" . TIMESTAMP . "'
  4.                 WHERE uid='{$_G['uid']}'");
  5.             if(!DB::affected_rows()) {
  6.                 DB::insert('common_onlinetime', array(
  7.                     'uid' => $_G['uid'],
  8.                     'thismonth' => $oltimespan,
  9.                     'total' => $oltimespan,
  10.                     'lastupdate' => TIMESTAMP,
  11.                 ));
  12.             }
  13.             $discuz->session->set('lastolupdate', TIMESTAMP);
  14.         }
复制代码
如果是会员登录论坛,判断最近更新时间与当前时间的差大于用户在线时间更新时长时,会更新common_onlinetime表(记录会员在线时间)里对应用户的对应字段的值,若没有对应用户,则添加一条记录。
  1.        foreach($discuz->session->var as $k => $v) {
  2.             if(isset($_G['member'][$k]) && $k != 'lastactivity') {
  3.                 $discuz->session->set($k, $_G['member'][$k]);
  4.             }
  5.         }

  6.         foreach($_G['action'] as $k => $v) {
  7.             $discuz->session->set($k, $v);
  8.         }

  9.         $discuz->session->update();

  10.         $updated = true;
复制代码
然后程序开始更新session(针对所有用户,包括未登录的游客),将session数据存到common_session表里。
  1. if($_G['uid'] && TIMESTAMP - $ulastactivity > 21600) {
  2.             if($oltimespan && TIMESTAMP - $ulastactivity > 43200) {
  3.                 $total = DB::result_first("SELECT total FROM ".DB::table('common_onlinetime')." WHERE uid='$_G[uid]'");
  4.                 DB::update('common_member_count', array('oltime' => round(intval($total) / 60)), "uid='$_G[uid]'", 1);
  5.             }
  6.             dsetcookie('ulastactivity', authcode(TIMESTAMP, 'ENCODE'), 31536000);
  7.             DB::update('common_member_status', array('lastip' => $_G['clientip'], 'lastactivity' => TIMESTAMP, 'lastvisit' => TIMESTAMP), "uid='$_G[uid]'", 1);
  8.         }
  9.     }
  10.     return $updated;
  11. }
复制代码
最后根据用户最近的更新的时间,将计算出的用户在线时间,更新到common_member_count表(统计用户记录信息表)里,我们看到的在线时间就是从此表里读取出来的,并且记录当前时间为用户最近活跃的时间。(注意:common_member_count表中的在线时间是每12个小时更新一次)

以上有两个关键点:
在线时间的统计是由该函数执行和保存的,在线会员显示是直接读取的common_session表中的数据

此问题已得到解决.论坛每15分钟统计一次论坛在线情况.如仍有用户出现此问题请在本帖后跟帖描述您的具体情况,我们会在第一时间给予解决.
程序是每15分钟更新一次数据库也就是说.当您登陆论坛时 程序在您登陆之的前一分钟更新过SESSION 缓存,那么您在接下来的13分钟内都会显示离线,直至第二次程序再次运行更新SESSION此时,您的状态会显示在线!
PS: 只开着网页没有进行任何操作是不会更新在线时间的.因为SESSION存在生命周期!


另外,请不再次发帖子说自己的时间不正确,请您理解在线时间更新原理.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要画出三维空间中的抛物线,可以先根据起点和终点的坐标计算出抛物线的参数,然后再在时间轴上逐一计算抛物线经过的点,最终连接这些点就可以画出抛物线。 具体步骤如下: 1. 根据起点和终点的坐标,计算出抛物线的参数,包括抛物线的高度、抛物线的开口方向、抛物线的顶点坐标等。 2. 设定时间轴的时间步长,根据时间步长逐一计算出抛物线经过的点的坐标。可以使用二次函数的标准式 y=ax^2+bx+c,其中 x 表示时间,y 表示高度。将抛物线的参数带入该式中计算出 a、b、c 的值,再根据时间轴上的时间计算出对应的 x 值,就可以得到抛物线上对应时间的高度和横纵坐标。 3. 将计算出的点连接起来,就可以画出抛物线。 以下是使用 C++ 实现的示例代码: ```c++ #include <iostream> #include <cmath> using namespace std; struct Point { double x; double y; double z; }; // 根据起点和终点计算抛物线参数 void calcParabola(Point start, Point end, double& a, double& b, double& c) { double dx = end.x - start.x; double dy = end.y - start.y; double dz = end.z - start.z; double v0 = sqrt(dx * dx + dy * dy + dz * dz); // 初始速度 double g = 9.8; // 重力加速度 double t = v0 / g; // 抛物线总时间 double h = start.y + v0 * v0 / (2 * g); // 抛物线顶点高度 a = -g / 2; b = v0; c = start.y - h; } // 根据抛物线参数和时间计算点坐标 Point calcPoint(double a, double b, double c, double t) { Point p; p.x = b * t; p.y = a * t * t + b * t + c; p.z = 0; return p; } int main() { Point start = {0, 0, 0}; // 起点 Point end = {10, 5, 20}; // 终点 double a, b, c; calcParabola(start, end, a, b, c); double dt = 0.1; // 时间步长 for (double t = 0; t <= b / a; t += dt) { Point p = calcPoint(a, b, c, t); cout << "(" << p.x << ", " << p.y << ", " << p.z << ")" << endl; } return 0; } ``` 在该示例代码中,我们先定义了起点和终点的坐标,然后调用 `calcParabola` 函数计算出抛物线的参数,最后使用 `calcPoint` 函数计算出每个时间点上抛物线经过的点的坐标,将其输出即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值