【问题标题】:How does Long Polling or Comet Work with PHP?长轮询或彗星如何与 PHP 一起工作?
【发布时间】:2013-02-03 05:12:48
【问题描述】:

我正在为我的网站制作通知系统。我希望登录的用户在收到通知时立即注意到。正如许多人所说,只有几种方法可以做到这一点。

有人正在编写一些 javascript 代码来询问服务器“是否有任何新通知?”在给定的时间间隔内。它被称为“轮询”(我应该是对的)。

另一个是“长轮询”或“彗星”。正如维基百科所说,长轮询类似于轮询。无需每次都询问新通知,当有新通知可用时,服务器将它们直接发送给客户端。

那么我如何在 PHP 中使用长轮询? (不需要完整的源代码,但需要一种方法) 它的架构/设计到底是什么?

【问题讨论】:

  • while (!$response) { $response = do_something(); sleep(1); } echo $response;
  • 有趣的问题,正是我要找的问题。我将悬赏 +50
  • 我认为对于某些网络服务器来说,长轮询可能是一个问题(不过自从我读到任何关于它的东西以来已经很久了)。太多打开的连接等。
  • @NickSlash 有什么问题?长轮询不是一个好方法吗?
  • 长轮询并没有什么问题,它只是传统的网络服务器不是为了做到这一点而设计的。 @louis-philippe-huberdeau 的回答解释了这一点。

标签: php javascript ajax long-polling polling


【解决方案1】:

长轮询的基本思想是您发送一个请求,然后服务器不会响应或终止该请求,直到某些所需的条件。 IE。服务器端不会通过发送响应来“完成”服务请求。您可以通过在服务器端循环执行来实现这一点。

想象一下,在每个循环中,您都进行了一次数据库查询,或者您需要做的任何事情来确定您现在需要的条件是否为真。只有当它是你打破循环并将响应发送给客户端。当客户端收到响应时,它会立即重新发送“长轮询”请求,这样就不会错过下一个“通知”。

服务器端 PHP 代码的简化示例可能是:

// Set the loop to run 28 times, sleeping 2 seconds between each loop.
for($i = 1; $i < 29; $i++) {

    // find out if the condition is satisfied.
    // If YES, break the loop and send response     

    sleep(2);
}
// If nothing happened (the condition didn't satisfy) during the 28 loops,
// respond with a special response indicating no results. This helps avoiding
// problems of 'max_execution_time' reached. Still, the client should re-send the
// long-polling request even in this case.

【讨论】:

  • 你能举个简单的例子吗?我将提供 +50
  • 在服务器端检查新通知的循环?这会减慢服务器的速度。会吗?
  • @PHP NooB 简单示例包括在内。
  • @Pravinda Amarathunga 嗯,有时您确实必须进行数据库查询或通过其他方式获取数据...
  • @MarcellFülöp 其实我是个菜鸟,我需要更多的帮助。我昨晚花了 2 个小时,从this video 写下脚本,即使我最终使脚本工作并根据需要运行,我也不知道在哪里放置您的代码,这里是 JavascriptPHP 脚本我写下来了。那么,我应该把你的代码放在哪里呢?
【解决方案2】:

您可以使用(或研究)一些现有的实现,例如Ratchet。还有一些其他的。

基本上,您需要避免让 apache 或 Web 服务器处理请求。就像使用 node.js 服务器一样,您可以从命令行启动 PHP,并使用 server socket 函数创建服务器并使用 socket_select 处理通信。

从技术上讲,它可以通过保持循环处于活动状态来通过 Web 服务器工作。但是,保持每个 HTTP 连接的 php 进程处于活动状态的内存开销通常太高。创建自己的服务器允许您在连接之间共享内存。

【讨论】:

  • 在经典的轮询方法中,没有(或更少)问题比彗星?
  • 经典的轮询方法也有很大的开销,因为它会显着增加服务器上的命中数。但是,内存不会在轮询之间保持分配。
【解决方案3】:

我最近对聊天应用程序使用了长轮询。在做了一些研究并玩了一段时间之后,我会推荐一些东西。

1) 不要长时间轮询超过 20 秒。某些浏览器会超时。我通常将我的长轮询设置为运行大约 20 秒,然后在此时发回一个空响应。然后你可以使用javascript重新启动长轮询。

2) 浏览器每隔一段时间就会挂起。为了帮助添加第二级错误检查,我有一个 javascript 计时器运行 30 秒,如果在 30 秒内没有响应,我会放弃 ajax 调用并重新启动它。

3) 如果您使用 php,请确保您使用 session_write_close()

4) 如果您在 Jquery 中使用 ajax,您可能需要使用 abort()

【讨论】:

    【解决方案4】:

    您可以找到答案here。更多细节here。在使用 jquery 时,您应该记得使用$.ajaxSetup({ cache:false });

    【讨论】:

    • 你应该在这里解释一下,而不是仅仅通过提及链接。
    猜你喜欢
    • 2011-01-02
    • 2014-01-11
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多