2

我是这个网站的新手,所以我真的希望我能提供有关我的问题的所有必要信息。

我一直在尝试使用长轮询创建“新消息到达通知”。目前我正在通过window.onLoad我网站中每个页面的事件发起轮询请求。

在服务器端,我有一个无限循环:

while(1){
 if(NewMessageArrived($current_user))break;
 sleep(10);
}
echo $newMessageCount;

在客户端,我有以下(简化的)ajax 函数:

poll_new_messages(){
 xmlhttp=GetXmlHttpObject();
 //...
 xmlhttp.onreadystatechange=got_new_message_count;
 //...
 xmlhttp.send();
}

got_new_message_count(){
 if (xmlhttp.readyState==4){
  updateMessageCount(xmlhttp.responseText);
  //...
  poll_new_messages();
 }
}

问题是每次页面加载时,上述循环都会重新开始。结果是每个用户都有多个无限循环,最终使我的服务器挂起。

*该NewMessageArived()函数查询 MySQL DB 以获取新的未读消息。

*在我运行的 php 脚本的开头start_session()以获取$current_user值。

我目前是该站点的唯一用户,因此我很容易通过写入time()此循环内的文件来调试此行为。我看到的是该文件在 10 秒内被写入的频率超过一次,但它仅在我从一页到另一页时才开始。

请让我知道是否有任何其他信息可能会有所帮助。

谢谢你。

4

3 回答 3

1

我想我找到了解决问题的方法。如果有人能说出这是否是 COMET 中使用的技术以及该解决方案的可扩展性,我将不胜感激。

我使用了这样一个基于用户的信号量:

$sem_id = sem_get($current_user);
sem_acquire($sem_id);
while(1){
 if(NewMessageArrived($current_user))break;
 sleep(10);
}
sem_release($sem_id);
echo $newMessageCount;
于 2009-11-24T19:59:57.570 回答
1

长轮询请求在 30 秒后超时似乎很常见。因此,在您的 while 循环中,您可以在 30 秒后回显“CLOSE”。

while(!$new_message && $timer < 30){
    $new_message = NewMessageArrived($current_user);
    if(!$new_message) {
        sleep(10);
        $timer += 10;
    }
}
if($newMessageCount) {
    echo $newMessageCount;
} else {
    echo 'CLOSE';
}

在 Javascript 中,您可以监听 CLOSE。

function poll_new_messages(){
    xmlhttp=GetXmlHttpObject();
    //...
    xmlhttp.onreadystatechange=got_new_message_count;
    //...
    xmlhttp.send();
}

function got_new_message_count(){
    if (xmlhttp.readyState==4){
        if(xmlhttp.responseText != 'CLOSE') {
            updateMessageCount(xmlhttp.responseText);
        }
        //...
        poll_new_messages();
    }
}

现在,无论如何,PHP 将在 30 秒内返回响应。如果您在页面上使用停留,并且您收到 CLOSE,您只是不更新​​页面上的计数,然后重新询问。

如果用户移动到新页面,您的 PHP 实例将在 30 秒内停止循环,并返回响应。但是,在新页面上,关心该连接的 XHR 不再存在,因此它不会启动另一个循环。

于 2009-11-23T21:02:21.277 回答
0

您可以尝试connection_aborted()定期检查。请注意,connection_aborted()在您编写一些输出并完成flush().

事实上,仅仅周期性地产生一些输出可能就足以让 php 注意到连接自行关闭,并自动终止你的脚本。

于 2009-11-23T21:01:32.947 回答