2013-04-01 146 views
12

我正在寻找一个长时间轮询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 

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

要添加,没有设定的使用次数可能在网站上,所以我正在寻找一种有效的方式来做到这一点。

+0

这是一个很好的问题,我正要问同样的问题。 – samayo

回答

8

是的,你描述它的方式是长轮询方法是如何工作的。 您的示例代码有点模糊,所以我想补充一点,您应该在while循环内执行sleep()一小段时间,并且每次比较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); 
      }  
     }); 
} 
+0

欣赏答案!函数getLastCheckedTime包含什么?我知道你说过它返回上次访问数据库的时间,但我该如何判断? db中的列? – SeanWM

+0

另外,我是否应该在if语句中没有最后四行? – SeanWM

+0

是的'getLastCheckedTime();'必须返回db中列的结果,当插入新消息时它将自动更新。 最后四行不一定要在'if'语句中,因为只有当新数据被插入到数据库中时才会执行,因此只有'while'才会被中断。 –

1

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

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

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

从结构上看,关联表是迄今为止最好的。制作一张专门用于检查状态的新表格,列有三列:user_idmessage_idread_at。用法应该很明显。不在那里的任何组合都是未读的。

2

而不是添加新列作为last_checked您可以添加为last_checked_time。所以你可以从last_checked_timecurrent_time

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

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

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