长轮询 - 消息系统

时间:2013-04-01 12:21:22

标签: php long-polling

我正在研究使用jQuery和PHP对消息系统进行长时间轮询。我很想知道实现这一目标的最佳/最有效的方法。我的基础是Simple Long Polling Example

如果用户正坐在收件箱页面上,我想提取任何新邮件。我见过的一个想法是在消息表中添加last_checked列。 PHP脚本看起来像这样:

query to check for all null `last_checked` messages
if there are any...
while(...) {
    add data to array
    update `last_checked` column to current time
}
send data back

我喜欢这个想法,但我想知道别人怎么想。这是解决这个问题的理想方式吗?任何信息都会有所帮助!

要添加,网站上没有可用的设置数量,因此我正在寻找一种有效的方法。

4 个答案:

答案 0 :(得分:8)

是的,您描述的方式是长轮询方法通常如何工作。 您的示例代码有点模糊,所以我想补充一点,您应该在sleep()循环内执行while一小段时间,并且每次比较last_checked时间(它存储在服务器端)和current时间(这是从客户端发送的)。

这样的事情:

$current = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
$last_checked = getLastCheckedTime(); //returns the last time db accessed

while( $last_checked <= $current) {
    usleep(100000);
    $last_checked = getLastCheckedTime();
}

$response = array();
$response['latestData'] = getLatestData() //fetches all the data you want based on time
$response['timestamp'] = $last_checked;
echo json_encode($response);    

在你的客户端JS你会得到这个:

function longPolling(){
        $.ajax({
          type : 'Get',
          url  : 'data.php?timestamp=' + timestamp,
          async : true,
          cache : false,

          success : function(data) {
                var jsonData = eval('(' + data + ')');
                //do something with the data, eg display them
                timestamp  = jsonData['timestamp'];
                setTimeout('longPolling()', 1000);
          },
          error : function(XMLHttpRequest, textstatus, error) { 
                    alert(error);
                    setTimeout('longPolling()', 15000);
          }     
       });
}

答案 1 :(得分:2)

您可以添加last_checked,而不是将新列添加为last_checked_time。这样您就可以将数据从last_checked_time提取到current_time

(i.e) DATA BETWEEN  `last_checked_time` AND `current_time`

答案 2 :(得分:1)

如果您只有一个用户,那很好。如果你不这样做,你会遇到并发症。你也可以通过这样做来运行一大堆SELECT查询。

由于PHP没有任何跨客户端事件驱动的可能性,我一直坚信PHP和长轮询本身不能正常工作。这意味着您需要每秒/ 2秒/ 5秒检查一次数据库,而不是依赖于事件。

但是,如果您仍想这样做,我会让您的消息传递系统在用户有消息时在目录中写入文件[nameofuser] .txt,并使用此触发器检查消息是否存在。如果文件存在且不为空,则触发请求以获取消息,处理,反馈然后删除文本文件。这将减少您的SQL开销,而(如果您不小心)增加磁盘IO。

结构方面,关联表是目前最好的。创建一个专用于检查状态的新表,其中包含三列:user_id message_id read_at。用法应该是显而易见的。没有在那里的任何组合都是未读的。

答案 3 :(得分:1)

您可以创建名为:checked的列,而不是创建名为last_checked的列。 如果保存数据库中的所有消息,则可以更新数据库中的字段。例如:

  1. 用户1向用户2发送消息。
  2. PHP使用长轮询系统接收消息,并将消息保存在表中。
  3. 用户2在线时会向服务器发送信号,通知服务器用户1已准备好接收消息
  4. 服务器检查表中所有未“检查”的消息并将其返回。