首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • php当未正常退出时,如何判断注册用户是否在线?记录最后登录时间然后定时去检查是否过期的就不用说了 [已结贴,结贴人:duanjianbo26]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 揭贴率:
    发表于:2008-08-21 11:11:10 楼主
    最近在博客中要实现一个用户是否在线功能,整了几天没想出个好办法!
    网上也GOOGLE,百度了很多,发现把session存入数据库比较准确。使用的方法是用函数
    session_set_save_handler(   
      "sess_open",   
      "sess_close",   
      "sess_read",   
      "sess_write",   
      "sess_destroy",   
      "sess_gc");   

    但是由于对这个函数理解不是很深,有几个疑虑,所以也不敢贸然改为数据库存储SESSION的方式。下面我把我的的问题告诉大家,希望能在这解决这个问题。
    1.首先大家都知道session默认的存储方式是文件存储,如果我改为用这个函数的话,那么网站其他的session会不会受到影响。就是我只要将用户是否在线的session存入到mysql中,用session_set_save_handler函数之后其他的session还是以原来的方式存储吗?
    2.session_set_save_handler函数中sess_read不是有个参数是sessionkey吗?为什么我没有任何session的情况下echo sessionkey会有值(一字符串,应该就是sessionid)?这个值是代表哪个session?
    3.谁能把这六个参数的具体功能和如何执行解释下?

    50  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jazzyfree
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 11:33:361楼 得分:0
    给用户表加个字段:最后活动时间
    用户只要一有动作就更新这个字段
    判断在线:拿当前时间和最后活动时间比较,如果小于某个值就认为他在线
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fxs_2008
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 3

      2

    发表于:2008-08-21 12:19:552楼 得分:10
    1.不会
    2.只有一个session_id
    3.这个几个可以看作是"事件"吧

    至于你所说的检验是否在线,没有好办法

    最好的办法是用户关闭浏览器时向服务器通知,但不好做
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 14:26:443楼 得分:0
    我测试下了下,代码如下:
    PHP code
    @header("content-Type: text/html; charset=UTF-8"); require('includes/configure.php'); //include database tables require('includes/database_table.php'); // set php_self in the local scope if (!isset($PHP_SELF)) $PHP_SELF = basename($_SERVER['SCRIPT_FILENAME']); // include the database class require(DIR_WS_CLASSES . 'db_mysql_class.php'); $db=new DbCom(); // make a connection to the database... now $db->connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE); $db->query("set names utf8"); $session = new session($db); session_start(); $_SESSION['webid']=117; $_SESSION['username']='duanjianbo'; class session { var $db; function session(&$db) { $this->db = &$db; session_module_name('user'); session_set_save_handler( array(&$this, 'open'), array(&$this, 'close'), array(&$this, 'read'), array(&$this, 'write'), array(&$this, 'destroy'), array(&$this, 'gc') ); session_start(); } function unserializes($data_value) { $vars = preg_split( '/([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\|/', $data_value, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE ); for ($i = 0; isset($vars[$i]); $i++) { $result[$vars[$i++]] = unserialize($vars[$i]); } return $result; } function open($path, $name) { return true; } function close() { return true; } function read($SessionKey){ $sql = "SELECT uid FROM sessions WHERE session_id = '".$SessionKey."' limit 1"; $query =$this->db->query($sql); if($row=$this->db->fetch_array($query)){ return $row['uid']; }else{ $this->db->query("insert into `sessions` set `session_id` = '$SessionKey'"); return ""; } } function write($SessionKey, $VArray) { require_once(DIR_WS_CLASSES . 'db_mysql_class.php'); $db1=new DbCom(); // make a connection to the database... now $db1->connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE); $db1->query("set names utf8");//这里为什么之前的$this->db的对象改变了 $SessionArray = addslashes($VArray); $data=$this->unserializes($VArray); $this->db=$db1; $sql = "update `sessions` set "; if(isset($data['webid'])){ $sql .= "uid = '".$data['webid']."', " ; } $sql.="`last_visit` = null " . "where `session_id` = '$SessionKey'"; $this->db->query($sql); return true; } function destroy($SessionKey) { $this->db->query("delete from `sessions` where `session_id` = '$SessionKey'"); return true; } function gc($lifetime) { $this->db->query("delete from `sessions` where unix_timestamp(now()) - unix_timestamp(`last_visit`) > $lifetime"); return true; } }

    在write方法中,如果不重新连接下数据库则会报错:is not a valid MySQL-Link resource ,var_dump($this->db)结果如下 object(DbCom)#1 (3) { ["query_num"]=> int(2) ["linkId"]=> resource(5) of type ([color=#FFFF00]Unknown) ["charset"]=> NULL } [/color]和正常的结果区别是["linkId"]=> resource(5) of type ([color=#FFFF00]mysql link)[/color]!这又是为什么呢?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 15:44:144楼 得分:0
    怎么我写入数据库的session记录怎么过了一个多小时还没被删除啊?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • songzairan
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 16:02:465楼 得分:0
    关注...
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 16:19:526楼 得分:0
    我发现,我退出清楚session后其数据库中的session值还存在,并且存放session的临时目录里面还有文件sess_44a9b527e2ddd4a1a6522e09b463bd5e报错着session的值!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • happy002
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 16:28:317楼 得分:0
    mark~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-21 17:40:138楼 得分:0
    用session_unset函数删除session时,触发不了自定义destroy方法!只有用session_destroy才能触发然后删除数据库的记录,但是session_destroy删除的是所有的session啊,问题是我不想删除所有的啊!还有用session_unset删除时数据库的session记录根本就没变过
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 10:32:589楼 得分:0
    没人帮忙啊,自己顶!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zhutimy
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-22 15:31:1910楼 得分:15
    引用 4 楼 duanjianbo26 的回复:
    怎么我写入数据库的session记录怎么过了一个多小时还没被删除啊?


    ; Define the probability that the 'garbage collection' process is started
    ; on every session initialization.
    ; The probability is calculated by using gc_probability/gc_divisor,
    ; e.g. 1/100 means there is a 1% chance that the GC process starts
    ; on each request.

    session.gc_probability = 1
    session.gc_divisor    = 100

    php.ini
    ====================
    最好的办法莫过于打电话叫他点"退出"了 :)
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-26 09:48:3711楼 得分:0
    据同事说session_set_save_handler函数没用?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-29 17:43:4912楼 得分:0
    这几天终于研究出来了,但是用之后发现此session根本不能跨页面传递!!!!郁闷。。。。
    为了证明是因为用了session_set_save_handler的原因,我把这个函数的功能屏蔽然后换上session_start(),即普通的session方式。发现一切ok!怎么办?什么原因啊?我要崩溃了
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ten789
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-30 03:15:3613楼 得分:5
    session_set_save_handler和session_start是要同时存在的

    session_set_save_handler只是注册了自定义SESSION存储方式而不是用PHP系统的存储方式

    在使用session_set_save_handler的时候 SESSION的操作方法和不使用是一样的

    session_set_save_handler注册的函数 是不需要序列化和反序列化的

    3楼代码有错 SESSION的运行方式是先读 在程序运行完后运行注册的写函数
    应该把DB链接放在构造函数中 而且不应该在1个程序中有多个DB链接 全局变量或者其他方式传递DB链接

    对于清理函数 参数是超时的时间戳 只需要删除小于这个时间的SESSION就可以了

    3楼的数据结构有严重问题 时间应该用时间戳存储 而不是用那么复杂的时间格式

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-01 12:30:1414楼 得分:0
    引用 13 楼 ten789 的回复:
    session_set_save_handler和session_start是要同时存在的

    session_set_save_handler只是注册了自定义SESSION存储方式而不是用PHP系统的存储方式

    在使用session_set_save_handler的时候 SESSION的操作方法和不使用是一样的

    session_set_save_handler注册的函数 是不需要序列化和反序列化的

    3楼代码有错 SESSION的运行方式是先读 在程序运行完后运行注册的写函数
    应该把DB链接放在构造函数中 而且不应该在1个程序…

    session_set_save_handler和session_start是要同时存在的  程序里面是这样的

    应该把DB链接放在构造函数中 而且不应该在1个程序中有多个DB链接 全局变量或者其他方式传递DB链接  我是用参数传递进来初始化给$this->db的,其他函数都可用但在write函数里面会报错,报错原因在三楼已经说过了。
    最后不能跨页面的问题还是不知掉如何解决?目前解决方案是将session改为cookie
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-02 20:06:2815楼 得分:0
    Php版块的人气不怎么样啊,怎么一个帖子放了几天没人理呀?
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yunfeifan
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-02 21:06:1916楼 得分:10
    可以这个样子的,看看一些电子银行,当你关闭浏览器的时候,它会弹出一个alert,在弹出alert的同时,执行了logout程序,这样你就可以知道什么时候退出了。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • unlive
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-02 22:36:2417楼 得分:5
    16楼的这个意见不错。对于是否在线要求很严格的话,这个方法还是不错的。
    但是还是会存在意外中断,如电脑重启,强行关机等情况,这个时候,即使用户下线了,系统还是没得到下线的通知;
    因此加上一个无动作时间限制作为下线标志也是有必要的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Dereky
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-03 02:08:0318楼 得分:5
    个人觉得除非特别特别例外的应用(事实这种应用基本是不存在的),判断用户在线一定存在一定的误差,16楼的方法确实可行,但是在两种情况下会存在误差
    1:js没有获得 window.close动作
    2:用户意外操作,包括掉电,强行关机等

    设置一个cookies,超过设置的无动作时间,出现动作就写数据库标记,标记在线,否则则认为离线
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ph215405357
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-03 08:48:0619楼 得分:0
    引用 7 楼 happy002 的回复:
    mark~
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • duanjianbo26
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-03 08:53:1220楼 得分:0
    楼上说的都有道理,问题我已经实现了将session保存在myql数据库中,其他一切正常!只是session不能跨页面了。。。。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cskiller2049
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-09-10 11:27:2221楼 得分:0
    mark
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved