今天帮人改了个在线聊天室的作业,用PHP+Ajax实现了一个长轮询(long polling)。
服务端主要是两点,一个是用set_time_limit(0);
去除页面执行时间的限制。再就是用一个while
判断是否有数据,没有的话就sleep
几秒钟再重新取。
客户端就是一个Ajax,把当前页面的最后一条的记录传给服务器,请求这之后的数据。回调函数sucess
和error
中都包括调用当前函数。以保证会一个接一个的不断请求,其实这里用setInterval()
也可以。如果要用回调的话,Ajax里需要加上cache: false
,否则某些浏览器(如IE10)会在第二次请求的时候拿到304 Not Modified
,浏览器会瞬间卡死。
具体的代码实现非常短,贴在下面:
chatview.php
<?php
set_time_limit(0);
//require('chatconfig.php');
header('Content-type: application/json');
//开始计算当前页面循环时间
$begintime = time();
//从某个ID开始取
$begin = 0;
if(isset($_GET['begin']) && is_numeric($_GET['begin']) && $_GET['begin']>0)
{
$begin = $_GET['begin'];
}
$sql = sprintf("SELECT * FROM (SELECT * FROM chat WHERE id > '%d' ORDER BY id DESC LIMIT 100) t ORDER BY id ASC", $begin);
$result = $mysql->query($sql);
//如果没有取到数据,且执行时间小于30秒,则暂停1秒后重新查询
while($result->num_rows == 0 && (time()-$begintime<30))
{
sleep(1);
$result = $mysql->query($sql);
}
//用JSON返回数据
$ret = array();
if ($result->num_rows > 0)
{
while($row = $result->fetch_assoc())
{
$ret[]=array('id'=>$row["id"],'nick'=>$row["nick"],'content'=>$row["content"]);
}
}
echo json_encode($ret);
$mysql->close();
?>
JavaScript代码(jQuery)
function chat_update()
{
$.ajax({
url: "chatview.php",
//取最后一条ID之后的数据
data: {begin: window.Lastid},
cache: false,
success: function (data) {
//将数据填入页面上
resolveMsg(data);
chat_update();
},
error: function(){
chat_update();
}
});
}
set_time_limit会导致死循环,你这个跑久了服务器会崩的。可以用RS服务实现实时推送,开发文档见http://doc.hostker.com/realtime-sock.html
fdfsdaf