12

我正在考虑使用 jQuery 和 PHP 对消息系统进行一些长时间的轮询。我很想知道实现这一目标的最佳/最有效的方法。我基于这个简单的长轮询示例

如果用户坐在收件箱页面上,我想拉入任何新消息。我看到的一个想法是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

4 回答 4

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);
          }     
       });
}
于 2013-04-04T08:33:05.613 回答
2

而不是添加新列,last_checked您可以添加为last_checked_time. 这样您就可以将数据last_checked_timecurrent_time.

(i.e) DATA BETWEEN  `last_checked_time` AND `current_time`
于 2013-04-01T12:30:13.857 回答
1

如果您只有一个用户,那很好。如果你不这样做,你会遇到并发症。通过这样做,您还将运行大量的 SELECT 查询。

一段时间以来,我一直坚信 PHP 和长轮询不能在本地工作,因为 PHP 没有任何跨客户端事件驱动的可能性。这意味着您需要每 2 秒/5 秒检查一次数据库,而不是依赖事件。

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

在结构方面,关联表是迄今为止最好的。创建一个专门用于检查状态的新表,包含三列:user_id message_id read_at. 用法应该很明显。任何不存在的组合都是未读的。

于 2013-04-01T12:26:39.440 回答
1

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

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