http://www.vgot.net/echo/?action=show&id=175
当在线访问者并未关闭浏览器但超时没有更新页面,当其它访问者访问时因为前访问者的数据超时而被程序丢弃,导致前访问者的数据丢失,当前访问者更新页面时,因为已经有通信ID,数据不会被存储,所以会丢失一些在线的人。
此BUG修复方法为将 38 行改为
PHP代码
if(isset($_COOKIE[$cookiename]) and array_key_exists($_COOKIE[$cookiename],$nowonline)) {
这样如果前访问者再次更新页面,如果他的数据不存在,将会为他更新通信ID,这样便不会造成统计丢失。
以下是更改后带有IP数据的在线人数统计,此版本BUG修复在第 45 行
PHP代码
<?php
/*
@ PHP 在线人数统计程序
Copyright (c) www.vgot.cn by Pader 1:25 2009年1月7日
Version: 1.0.2
Homepage:http://www.vgot.cn
QQ: 270075658
How to use it: <script src="online.php"></script>
note: 一般独立在线人数统计程序都是统计在线的IP数,而这并不准确
例如局域网的访问者,比如公司,学校机房和网吧,虽然内网IP不同,但是外网IP都是一样
如果同一个局域网的无论多少人人访问你的网站则只被认为是一个人
这个小巧的程序解决了此问题,它以电脑为单为,每台电脑便算一个访问者
当然因为使用的是COOKIE,如果你在同一台电脑上使用两种不同核心的浏览器访问那就别当别论了
*/
$filename = 'online.txt'; //数据文件
$cookiename = 'VGOTCN_OnLineCount'; //cookie名称
$onlinetime = 600; //在线有效时间,单位:秒 (即600等于10分钟)
$online = file($filename);
$nowtime = time();
$nowonline = array();
/*
@ 获取当前访问者IP
虽然并不以 IP 来统计,但这里需要获取 IP 存储以方便其它程序统计
*/
$ipx = $_SERVER['HTTP_X_FORWARDED_FOR'];
$ip = (($ipx != '') && ($ipx != 'unknown')) ? $ipx : $_SERVER['REMOTE_ADDR'];
/*
@ 得到仍然有效的数据
*/
foreach($online as $line) {
$row = explode('|',trim($line));
$sesstime = trim($row[1]);
if(($nowtime - $sesstime) <= $onlinetime) { //如果仍在有效时间内,则数据继续保存,否则被放弃不再统计
$nowonline[$row[0]] = $sesstime.'|'.$row[2]; //获取在线列表到数组,会话ID为键名,最后通信时间与IP为键值
}
}
/*
@ 创建访问者通信状态
使用cookie通信
COOKIE 将在关闭浏览器时失效,但如果不关闭浏览器,此 COOKIE 将一直有效,直到程序设置的在线时间超时
*/
if(isset($_COOKIE[$cookiename]) and array_key_exists($_COOKIE[$cookiename],$nowonline)) { //如果有COOKIE即并非初次访问则不添加人数并更新通信时间
$uid = $_COOKIE[$cookiename];
} else { //如果没有COOKIE即是初次访问
$vid = 0; //初始化访问者ID
do { //给用户一个新ID
$vid++;
$uid = 'U'.$vid;
} while (array_key_exists($uid,$nowonline));
setcookie($cookiename,$uid);
}
$nowonline[$uid] = $nowtime.'|'.$ip; //更新现在的时间状态
/*
@ 统计现在在线人数
*/
$total_online = count($nowonline);
/*
@ 写入数据
*/
if($fp = @fopen($filename,'w')) {
if(flock($fp,LOCK_EX)) {
rewind($fp);
foreach($nowonline as $fuid => $finfo) {
$fline = $fuid.'|'.$finfo."\n";
@fputs($fp,$fline);
}
flock($fp,LOCK_UN);
fclose($fp);
}
}
echo 'document.write("'.$total_online.'");';
?>