PHP长轮询问题

时间:2013-11-06 10:38:45

标签: java php mysql ajax long-polling

我有一个用作管理面板的Web应用程序。它有一个实时聊天选项,可以与另一端的作者(员工)联系。 Web应用程序使用以下PHP代码来检查在线编写器。

$q = 0;
$lasttime = isset($_POST['timestamp']) ? $_POST['timestamp'] : 0;
while ($q<5){
    sleep(3);
    $wresult = $db->query("SELECT writer_alias FROM tblwriter WHERE writer_isactive=1 AND (UNIX_TIMESTAMP(NOW())-last_activity)<10");
    if ($wresult->num_rows){ break; }
    ++$q;
}
if ($wresult->num_rows){
    while ($row = $wresult->fetch_object()){ $writers[] = $row; } 
    $wresult->free(); 
}
echo json_encode(
    array(
        "writers" => $writers,
        "now" => time()
    )
);

在应用程序上,以下javascript代码处理PHP响应并再次调用ajax以完成循环。

function UpdateCHAT(){
    $.ajax({ 
        type: "POST", 
        url: "liveserver.php", 
        data: {update:"1",timestamp:lastime}, 
        success: 
            function(data1){
                if (data1 == null){ 
                    $(".onlinechat i").removeClass("icon-white"); 
                }else{ 
                    lastime = user_signin = Number(data1.now);
                    if (!data1.writers.length){ 
                        $(".onlinechat i").removeClass("icon-white"); 
                    }else{
                        $(".onlinechat i").removeClass("icon-white");
                        $.each(data1.writers,function(j) {
                            $("#writer_"+data1.writers[j].writer_alias).find("i").addClass("icon-white");
                        }); 
                    }
                }
            }, 
        dataType: "json",
        timeout: 60000,         
        complete: 
            function(){
                UpdateCHAT(); 
            }
        }
    );
}

一切都工作得很好,除了我无法想办法知道离线作者,因为PHP代码旨在检查在线作家,但这意味着如果作家在线一次,他将保持在线(在应用程序上),直到PHP代码死掉并返回空写入器。

希望我能够解释我的观点。这个问题更多的是与想法而不是一段代码有关。任何意见都表示赞赏。

感谢。

1 个答案:

答案 0 :(得分:0)

让PHP代码总是在一段时间(如2分钟)后返回,并且结果为空(即没有新的聊天行)。

然后,JS将立即执行新请求。如果没有,那么用户就是离线。保留last_request时间戳,如果它超过用户离线的2 + e分钟。


您可以尝试检测PHP中连接何时关闭。设置ignore_user_abort(true),这样您就可以控制脚本何时死亡。然后使用connection_aborted()检查客户端是否已关闭。如果他知道他就离开了。

如果用户打开两个窗户,则会出现潜在问题:关闭一个并不意味着他离开了,但这可能是可以接受的;用户将 blip 一段时间。


另一种解决方案是使用单独的ping请求,它只是告诉你“是的,我还在这里”。如果你有一段时间没有得到其中一个用户可能离线。