注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

阿飘的博客

十里平湖霜满天 寸寸青丝愁华年

 
 
 

日志

 
 

PHP在线人数统计  

2009-05-31 18:01:00|  分类: php |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
如何实现在线人数的显示?
说说思路:)


  在论坛里有人问我如何统计在线人数?我也不知道什么是最好的方法。下面是本站的实现的原理,我把写出来,供大家参考。这只是我的方法,肯定不是最好的,还希望高手们予以指正。
  其实,要真正统计同时在并发在线的人数,是一件不太现实的事,这是因为HTTP协议是种无状态的协议。客户端向服务器发出一个请求时,服务器会马上建立一个新的TCP/IP连接,在该会话结束后,如页面完全入后,这个连接就关闭了。一般来说,在线人数指的定是在一定时间段内同时访问站点的人数,而不是基HTTP协议的并发连接数。
  让我们先来看看一个访客是如何访问一个网站的。他在浏览器的地址栏里输入了目标网站的地址,然后一段时间内持续浏览该网站的网页,最后,关闭浏览器或输入新的网址——浏览结束了。对于服务器端来,访客到来是可以知道的,访客在浏览页面也是可以知道的,可是怎么知道什么时候走的呢?由于HTTP协是无状态的,所以无法知道。通常的做法是记下访客最后一次浏览站点页面的时间。如果该访客在一个特的时间内没有新的动作,那么可以认为他走了。
  根据上面的这个思路,我觉得最好用数据库,因为数据库要比其他方法如文本文件的效率要高。下面的子是使用MySQL的,很容易使用其他类型的数据库系统。然后,在所有的页面中调用这个PHP文件,一方面新数据,另一方面可以显示在线的人数。但是,有一个问题--到底在多长时间内访问的人算是并发的呢?般来说,是半个小时,也就是1800秒,具体的要根据网站的情况来确定。这个时间越长,统计出的并发在的人数就越多。本站的是15分钟,900 秒。用访问者的IP地址表示一个访问者是个不错的方法。在拨号上的情况下,被分配了相同IP地址的两个用户在短时间内浏览同一个网站的概率是很小的。

  首先,用MySQL的工具建一个表:
CREATE TABLE ccol(
id integer not null auto_increment, #记录的ID
ip char(15) not null, #访问者的IP地址
dtstamp datetime not null, #最后访问时间
uri char(255), #访问者请求的URI
primary key (id)
);
  然后,写一段PHP代码:
<?
/*
文件:ccol.php - ConCurrent OnLine statistics
目的:统计同时在线浏览的人数
作者:Hunte, hunte@phpuser.com
修改:2000-4-25
*/
$duration=1800;
require "db.php";
//包含DBSQL,详情可以参考我的另一篇文章
$ccol=new dbSQL;
$ccol->connect();
$ccol->query("DELETE FROM ccol WHERE (UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(dtstamp))>$duration");
//删除超过半小时的记录
$ccol->query("SELECT * FROM ccol WHERE ip='$REMOTE_ADDR'");
//判断当前的IP是否在该表中存在
if ($ccol->nf())//有?
{
$ccol->next_record();//下移找到的记录数组的指针
$id=$ccol->f('id');
$ccol->query("UPDATE ccol SET dtstamp=now(), uri='$REQUEST_URI' WHERE id=$id");
//设置最后访问时间和访问页面
}
else//没有
{
$ccol->query("INSERT INTO ccol VALUES (0, '$REMOTE_ADDR', now(), '$REQUEST_URI')");
}
$ccol->query("SELECT COUNT(*) AS ccol FROM ccol
WHERE (UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(dtstamp))<=$duration");
//找出在半个小时内的记录,后面的WHERE子句可有可无--超出时间的已经被删除了
$ccol->next_record()
echo "在线人数:", $ccol->f('ccol');
$ccol->free_result();
?>
怎么用呢?在站点的每个页面的上面调用这个程序,举例来说:
--index.php
...
<!--显示在线人数->
<?require ../stats/ccol.php3?>
...
  当然,这段代码还有改进的余地。例如,在每次调用是都要删除半小时前的记录,这是没有必要而且会
降低效率。可以一个什么办法过更长的时间再做,比如6小时。大家自个儿想想吧,我就不说了。
这种方法只要稍做修改,就可以派上别的用处,如SESSION的管理、网站的访问统计分析等。


这是一个文本的,你看看吧!你事先建上文件onlin.txt,
<?
$datafile = 'online.txt'; // 数据文件,如果是linux/unix系统,需要把文件属性设置为777或者666
$onlineTime = 30; // 在线的时间差秒数,这里设置为半分钟
$timestamp = time(); // 取得当前的Unix时间戳
$dat = file($datafile); // 将数据文件读入数组
$count = count($dat); // 取得当前的数据记录数目
$onlineCount = 1; // 在线人数,起始就是1,当前的请求者自己
$insertMe = true; // 判断是否要插入当前请求者的记录,如果当前数据中没有此IP的记录就加入
for($i = 0; $i < $count; $i++) {
$dat[$i] = chop($dat[$i]); // 去处记录尾部的
list($ipadd, $requestUri, $lastRequest) = explode('│', $dat[$i]); // 取得数据
if($ipadd == $REMOTE_ADDR) { // 如果IP和当前请求者的IP一致,就更新Unix时间戳
$dat[$i] = $ipadd.'│'.$requestUri.'│'.$timestamp."";
$insertMe = false;
} else {
// 如果IP和当前请求者IP不一致,那么判断是否在线
if($lastRequest < ($timestamp - $onlineTime)) {
// 不在线,删除本条数据记录
$dat[$i] = '';
} else {
// 在线,加上尾部的
$dat[$i] .= "";
$onlineCount++; // 在线人数加1
}
}
}
// 用Javas cript输出结果
echo"$onlineCount";

// 将新的数据整合成为字符串
$newDat = join('', $dat);
if($insertMe) {
// 判断是否需要加入当前请求者的记录
$newDat .= $REMOTE_ADDR.'│'.$REQUEST_URI.'│'.$timestamp."";
}
// 写入数据文件
$fp = fopen($datafile, 'w');
fwrite($fp, $newDat);
fclose($fp);
?>


以下是我曾经发表的帖子的内容,只说了做在线人数统计的原理:
关于论坛在线用户显示模块实现的问题。
我 的论坛(http://ynwa.yeah.net)关于实现在线用户的模块是这样建立的(只讲原理,由于代码镶嵌在html里面,过于发散,不在这里列 出):当用户登陆时(打开我的论坛页面),把用户的登陆时间(精确到秒)记录到数据库该用户的相应列上。每个论坛页面都有一个隐藏的页面,该隐藏页面每隔 30秒刷新一次,当用户端的浏览器自动刷新时,把服务器的当前时间更新到登陆时间的列上,同时用服务器的当前时间减去其他在线用户的登陆时间(或者是已经 更新的时间),如果差值大于40秒,证明该用户的浏览器已经在远大于30秒的时间内没有刷新页面,也就意味着该用户已经离线。(因为在线的话,客户端的浏 览器一定会在30秒内自动刷新以更新登陆时间),同时删除该用户的登陆时间,以表示他离线。实际上,这个功能在我的论坛经过实践成功实现了。但有一个问题 我解决不了,就是当最后一个用户离线时,也就是说没有一个客户端打开我论坛的任何页面时,就没有页面会自动刷新了,也就是说,在最后一个用户离线后,如果 没有新用户登陆,即使过多长时间,页面也不会更新数据库,把该离线用户的登陆时间删除(我用查看用户的登陆时间列是否为NULL来判断用户是否在线)。那 么假设经过2小时后,一个用户登陆论坛,就会发现还有一个用户在线,实际上该用户已经离开了2个小时。


楼上的可以改进一下:
自动刷新是要的,还有一个 当用户登陆的时候拿登陆的时间和数据表上在线的比较
如果>30秒 就可以踢了 那样新用户登陆之后就不会看到尸体的存在了


谢谢,我记得我发这个帖是就是问”尸体“怎么处理,那时候是你告诉我方法的。谢谢。


以 上兄弟们的思路都是对的,就是通过一个可以容忍的时间差来判断,时间差之内就在线,之外就不在线了,方法可行,编码也不难,主要用于聊天室等地方。但我最 近发现了许多页面运用一种静态的显示方法,就是不用刷新页面。不求这个时间差,而是当用户进入后就定下了,既是一个用户(IP)进入就加一条记录,关闭就 删除这条记录(IP),当然这种方法有很大的局限性,但方法更简单。更多的用于一般主页上,当然也就不适合聊天室等对在线人员要求很高的页面。


提点建议:
可以用这个方法防止刷新一下统计就加一:
对于同一个ip(在登陆验证身份或者登陆首页的时候注册一个变量)在特定的时间内(比如30分钟)连续的访问只计数一次
  评论这张
 
阅读(2155)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017