PHP实现长轮询

今天帮人改了个在线聊天室的作业,用PHP+Ajax实现了一个长轮询(long polling)。

服务端主要是两点,一个是用set_time_limit(0);去除页面执行时间的限制。再就是用一个while判断是否有数据,没有的话就sleep几秒钟再重新取。

客户端就是一个Ajax,把当前页面的最后一条的记录传给服务器,请求这之后的数据。回调函数sucesserror中都包括调用当前函数。以保证会一个接一个的不断请求,其实这里用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();
        }
    });
}

标签: php, ajax

已有 2 条评论

  1. set_time_limit会导致死循环,你这个跑久了服务器会崩的。可以用RS服务实现实时推送,开发文档见http://doc.hostker.com/realtime-sock.html

  2. fdfsdaf

添加新评论