【问题标题】:Stopping a while loop php停止一个while循环php
【发布时间】:2013-05-22 11:24:47
【问题描述】:

对这个问题感兴趣 - 如何正确停止带有 sleep 的 while 循环。 我实施了“long poll”来快速更新网站上的信息(警告、其他信息)。

脚本的本质

1.我们会将GET-request发送到脚本所在的PHP-page。

2.脚本运行循环while

3.在本系列中,有 2 个条件和最后的 sleep(1),这会暂停循环的执行。

   - 如果循环运行更多秒 30 - 分别停止循环和脚本的执行。

   -如果您的网站有新信息,请说“提醒” - 将结果提供给用户并停止循环。

问题 如果用户关闭浏览器窗口或重新加载页面 - 在脚本上执行一个新查询,这将再次开始循环。但是在这种情况下,循环 while 的先前执行将不会停止,直到它们至少在其中工作了一个条件。如果用户向页面发送大量请求 - 服务器的内存开始启动,结果全部挂起,直到所有 while 都不会停止执行。

问题 如何停止循环和脚本作为一个整体,当您运行页面时重新加载或客户端? 此刻我做了以下事情。 当您运行我们生成的脚本时,我们会收到一个分配给变量的随机数,并且与会话相同。进一步内陆同时做一个条件,其中变量必须是会话的值。如果为假 - 停止循环。 如果我们在 new 上运行脚本 - 会话的值会发生变化,因此所有先前的性能都会在停止时发生变化。 我可以使用那个选项吗?多少是安全的?

UPDATE.PHP

 // Initialize the user's session
 $session = Session::instance();

        $rand = rand();
        $session->set('user_update_key', $rand);
        $key = $rand;

        $limit = 20;
        $seconds = 0;

        set_time_limit($limit + 1);

        while (TRUE) {
            if (Session::instance()->get('user_update_key') == $key) {

                if (there are updates. if there is - output) {
                    echo 'update information';
                    flush();
                    exit;
                }
                if ($seconds == $limit) { // complete the loop at the expiration of the time.
                    echo 'Close';
                    flush();
                    exit;
                }
                $seconds++;
            } else {
                unset($session, $rand, $key, $notice, $mysession, $last_notice, $limit, $notise_return, $seconds);
                flush();
                exit;
            }
            session_write_close();
            sleep(1);
            session_start();

}

【问题讨论】:

  • while (TRUE)
  • 可以使用继续;用于在循环内终止循环的关键字。
  • 你真的需要 session_write_close(); / session_start(); ?更新过程是如何启动的,是否可以简单地将超时设置为 30 秒?
  • 如何在javascript中使用setInterval进行循环,并将脚本简化为没有循环的Session::instance()->get('user_update_key') == $key
  • 如果用户手动开始对脚本执行大量请求 - 它会同时启动很多“while”,即加载服务器

标签: php comet long-integer long-polling


【解决方案1】:

请注意,一般来说 PHP 和 Apache 不适合长轮询。我不知道当你使用 nginx 时情况如何,但几个月前我不得不在 Apache 上做一些长时间的轮询工作。在我们开始生产之前,一切看起来都很好。事实证明,Apache 的限制使您无法维持长期连接。

在允许大约 20 个用户登录并打开 3-4 个网页卡后,服务器挂起并拒绝接受任何新请求。还有一些浏览器限制会阻止您维护与一台主机的过多 http 连接。虽然有解决方法 - 使用子域。

我试图弄清楚如何解决 id,在 StackOverflow 上问了十几个问题,最后一切都使用了 node.js + socket.io,它是轻量级的,可以轻松处理数千个同时连接。

我知道这篇文章没有回答您最初的问题,但在我花了几周时间开发一些不起作用的东西之后,我希望这些信息会对您有所帮助。 p>

【讨论】:

    【解决方案2】:

    您为什么不使用 cronjob 定期在后台运行进程,然后将 AJAX 放置在拉数据库检查警报的网页上。否则你会遇到性能问题。

    【讨论】:

    • 您的意思是,将为每个用户创建 cronjob,它在后台运行。一个ajax请求已经为他做了很久?
    • 意味着您有一个在后台运行的 cronjob,唯一的工作就是发送电子邮件。你仍然可以让它成为一个 PHP 脚本,它从数据库中获取所有需要发送的记录,然后发送它们。在网站/应用程序端,ajax 每隔 X 秒运行一次,以检查它是否需要显示来自数据库的任何警报,是否弹出警报或执行您希望它执行的操作。
    • 使用这项技术可以立即通知您吗?
    • 是的! AJAX 可以在您的页面上连续运行,并在数据库中适用某些条件或任何输入时更新您的屏幕。
    • 但是 Cronjob 明白要付出,而什么不是?那用户的身份是怎样的?
    【解决方案3】:

    您的 while 条件是不可改变的,而在实践中却不是。 如果成功,函数 sleep() 将返回 0,因此,如果您根据 sleep() 的返回值的变化重写您的 while 条件反应,那么它是否可以按设计工作,请参阅: http://php.net/manual/en/function.sleep.php

    对于线程和其他功能,了解您在哪个操作系统上工作始终很重要。我有 Ubuntu,它的反应与文档所述不同。

    function interruptedSleep(){
      $cond = true;
      while($cond){
       $i = sleep(10);
       if($i == 0){
         $cond = false;
       }
      }
     }
    

    当您通过关闭浏览器来中断睡眠时,sleep 函数将返回 0,while 循环将被中止,程序将在 while 之后直接继续。它不会抛出异常。

    【讨论】:

    • 按你说的设置。所有时间都显示为假。 :( 在这种情况下,页面是打开的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 2022-10-31
    • 1970-01-01
    • 2011-10-16
    • 2010-09-26
    • 2013-09-11
    相关资源
    最近更新 更多