PHP的在线人数统计[转帖]
现在很多网站或者论坛都有在线人数统计这个功能,管理员看着自己网站的在线人数不断增多,别有一番风味。那么这些在线人数统计是怎么做出来的呢? 
要实现在线统计,有两种方法。 
第一种是使用一个Socket和请求者连接,直到请求者的Socket断开,就把数据库中的记录删除,然而这种方法过于复杂。 
现在的网页都是基于HTTP协议,HTTP协议连接的生命期从请求者发出请求到HTTP回话结束完毕,也就是如果页面读取完毕,连接就关闭了。而第二种方法就是计算在某段时间之内的请求数目。 
知道了这个请求的数目,又怎么确定在线人数呢?我们在数据库中记录下此IP上次访问的时间,然后在统计在线人数的时候,如果某IP上次访问时间和当前时间的差值小于某个值的时候,就认为本用户仍然在线。而这个时间差值可以是5分钟,可以是15分钟,甚至可以是1个小时,要视不同网站而定。 
记录IP对应的访问时间,这里使用文本数据库,结构如下: 
IP地址 │ 请求的URI │ 最后请求的时间戳 
为什么要使用文本记录而不使用类似MySQL的SQL数据库呢?记录数据有方法,一是即使请求者已经被判定“不在线”,仍然在数据库中保留请求者的记录,但是这样子数据库的大小会像雪球一样越来越大,最终数据库不堪重负。第二种是当请求者被判定“不在线”的时候就将其所对应的记录删除,然而这样子就要频繁的写数据库,会造成数据库文件的分段,文本文件在这种情况下效率不会低于SQL数据库,甚至超过SQL数据库。 
下面就是统计在线人数的程序: 
--------程序间后----------- 如果在其他页面需要调用在线人数统计,只要在页面上面加入一句: 
<s cript src=在线统计程序的URL></s cript> 
就可以了。 
以上程序在Windows2000 Professional+Apache1.3.19+PHP 4.05和RedhatLinux7+Apache1.3.12+PHP4.04两个平台中测试通过,当文本文件中有10000条记录时,遍历时间耗时0.4秒。 
code: 
-------------------------------------------------------------------------------- 
<? 
$datafile = 'online.dat'; // 数据文件,如果是linux/unix系统,需要把文件属性设置为777或者666 
$onlineTime = 300; // 在线的时间差秒数,这里设置为5分钟 $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]); // 去处记录尾部的\n 
list($ipadd, $requestUri, $lastRequest) = explode('│', $dat[$i]); // 取得数据 
if($ipadd == $REMOTE_ADDR) { // 如果IP和当前请求者的IP一致,就更新Unix时间戳 
$dat[$i] = $ipadd.'│'.$requestUri.'│'.$timestamp."\n"; 
$insertMe = false; 
} else { 
// 如果IP和当前请求者IP不一致,那么判断是否在线 
if($lastRequest < ($timestamp - $onlineTime)) { 
// 不在线,删除本条数据记录 
$dat[$i] = ''; 
} else { 
// 在线,加上尾部的\n 
$dat[$i] .= "\n"; 
$onlineCount++; // 在线人数加1 



// 用Javas cript输出结果 
print <<< EOF 
document.write("在线人数:$onlineCount"); 
EOF; 
// 将新的数据整合成为字符串 
$newDat = join('', $dat); 
if($insertMe) { 
// 判断是否需要加入当前请求者的记录 
$newDat .= $REMOTE_ADDR.'│'.$REQUEST_URI.'│'.$timestamp."\n"; 

// 写入数据文件 
$fp = fopen($datafile, 'w'); 
fwrite($fp, $newDat); 
fclose($fp); 
?> 
来自:y10k