这是使用长轮询(Comet编程)的正确方法吗?

5

首先,我要感谢所有对新程序员非常有帮助的伟大人物。

我有一个关于长轮询的问题。我已经阅读了一些关于Comet编程的长轮询技术的文章。这种方法对我来说似乎很困难,因为有时还需要在服务器端安装一些脚本。

现在,我找到了一个关于长轮询的示例。它运行得很好,但我不确定它是否是正确的方法。这个示例脚本是一个类似聊天应用程序的php脚本,其工作原理如下:

  1. php脚本不断地检查data.txt文件,直到它被更改。
  2. 一旦data.txt被更改,新文本将被输出到网页上。

以下是php脚本:

<?php
$filename  = dirname(__FILE__).'/data.txt';

// store new message in the file
$msg = isset($_GET['msg']) ? $_GET['msg'] : '';
if ($msg != '')
{
    file_put_contents($filename,$msg);
    die();
}

// infinite loop until the data file is not modified
$lastmodif    = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
$currentmodif = filemtime($filename);
while ($currentmodif <= $lastmodif) // check if the data file has been modified
{
    usleep(500000); // sleep 500ms to unload the CPU
    clearstatcache();
    $currentmodif = filemtime($filename);
}

// return a json array
$response = array();
$response['msg']       = file_get_contents($filename);
$response['timestamp'] = $currentmodif;
echo json_encode($response);
flush();
?>

我不包括网页代码以保持问题简单。该网页只有一个div,每当data.txt文件更改时,它就会显示data.txt的文本。
我的主要问题点如下:
- 这种循环方法是长轮询服务器的适当方法吗? - 当服务器执行sleep()时,其他同时请求会发生什么? - 有没有任何技术可以减少由于长轮询的连续脚本而对服务器造成的负载? - 如果一个客户端开始这个长轮询请求后断开连接,我们如何知道并相应地停止该断开连接的客户端的脚本?
请指导我解决这个问题...谢谢
2个回答

5

是的,这是一个好主意。但请注意,这个脚本不会结束,并且每个用户都会生成一个PHP实例。我在服务器端使用了v8cgi长轮询逻辑。客户端发起XMLHttp请求(XHR)后,服务器开始间隔一段时间检查新输入。我在服务器端添加了一个计时器,每5分钟发送一次响应,如果客户端没有断开连接,则重新发送XHR,过程重复。

因此,每个服务器端机制的实例最长运行时间不超过5分钟,因为如果客户端断开连接,则服务器在5分钟后发送的响应不会跟随新的XHR。

该过程如下:

  • 客户端发送XHR
  • 服务器生成进程并定期检查更新
  • 如果需要发送某些更新:服务器发送响应
    • 客户端处理响应并重新启动XHR
    • 服务器生成进程并定期检查更新
  • 如果5分钟内没有更新:
    • 服务器发送响应并退出生成的进程
    • 客户端处理(空)响应并重新启动XHR
    • 服务器生成新进程并开始检查
  • 如果需要发送某些更新:服务器发送响应
  • [...]
  • 如果5分钟内没有更新:
  • [...]
  • 直到客户端断开连接(=服务器响应后没有新的XHR)

感谢您的回复。延迟实际上是500毫秒,即0.5秒。请注意,只要客户端浏览器打开页面,此脚本就会开始执行检查和更新例程。如果例如同时有1000个客户端浏览器打开,则服务器必须不断向它们发送响应。我们如何在php脚本中检查任何一个客户端是否断开连接,并为他们停止脚本,同时保持所有其他在线客户端的脚本开启。请解释一下。 - Naeem Ul Wahhab
仍在等待您的回复(看起来只有少数人知道长轮询,所以我没有得到其他答案)。请与我分享您的长轮询技术。我将非常感激。我们如何在php脚本中检查任何客户端是否已断开连接并为他们停止脚本,同时为所有其他在线客户端保持脚本打开状态。请帮忙! - Naeem Ul Wahhab
我已经对我的问题添加了一些解释,请仔细查看。 - Naeem Ul Wahhab
1
我在我的回答中确实描述了如何防止服务器保持打开大量脚本引擎实例。请仔细重新阅读答案。我会尝试更明确地说明。 - KooiInc

1

是的,这是一种简单而方便的方法,但并不是正确的方法,也不是最好的想法。因为它会受到很多问题的困扰,用户数量增加时会导致许多问题。

对于共享主机来说,这不是一个好主意,只有在用户数量不是很大且您拥有自己的服务器时,这种方法才能正常工作。如果您在共享主机服务器上使用此方法,则可能会遇到最大服务器资源使用会话锁定问题,并且HTTP服务可能会暂时不可用。

或者您可以使用现有的API进行聊天应用程序,或者拥有一个可以运行像node.js和类似服务器模块的脚本的专用服务器。


感谢您的回答和建议。 - Naeem Ul Wahhab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接