PHP中的“一劳永逸”

时间:2011-08-01 17:18:59

标签: php stream fire-and-forget

最终更新

好像我做了一个非常简单的错误。由于我已经有了一个流实现,因此我无法从流中读取:D


我正在尝试在PHP中实现 fire-and-forget 之类的功能。

  

From php.net

<?php
ignore_user_abort(true);
header("Content-Length: 4");
header("Connection: Close");
echo "abcd";
flush();

sleep(5);    
echo "Text user should not see"; // because it should have terminated
?>

如果我使用浏览器打开脚本,这是有效的。 (显示“abcd”)。 但是,如果我使用file_get_contents或某些 stream 库打开它,它将等待约5秒并显示第二个文本。

我正在使用PHP 5.2.11 / Apache 2.0


更新

我似乎对我想要完成的事情感到困惑。

我不想使用输出缓冲区隐藏输出(这是愚蠢的)。我希望客户端在服务器启动可能很长的进程(sleep(5))之前终止,并且我不希望客户端等待它(这就是“即发即忘”的意思,排序)。 输出缓冲区的使用仅仅是副作用。我在不使用输出缓冲区的情况下修改了示例代码。

我不明白的是:为什么这个脚本在从浏览器访问时的行为与使用file_get_contents("http://dev/test.php")或某些 stream 库在PHP中获取它时的行为不同?我在测试中看到的是,例如stream_get_contents实际上会在它返回任何输出之前阻塞5秒,这与我想要的完全相反。

UPDATE2

更多结果:

  • 浏览器会以某种方式响应flush()。我无法弄清楚如何使用PHP中的 streams 复制此行为,我的流阻止。
  • 我已尝试fread,发现其行为与stream_get_contents类似。
  • 指定maxlength无效,它仍将阻止约5秒。
  • 更改阻止模式无效(除了生成更多的调用to stream_get_contents())。在返回任何东西之前它会等待约5秒钟。
  • stream_set_read_buffer没有效果(在PHP 5.3.5服务器上测试)

3 个答案:

答案 0 :(得分:0)

第二部分文字正在显示,因为您正在使用ob_end_flush()ob_end_clean()停止输出缓冲。当发生这种情况时,PHP会正常输出内容。尝试以下内容:

<?php

ob_start(); // turn on output buffering
print "Text the user will see.";
ob_flush(); // send above output to the user and keep output buffering on

print "Text the user will never see";

ob_end_clean(); // empty the buffer and turn off output buffering. your script should end here.

?>

ob_end_clean()出现在脚本末尾非常重要。它会清空缓冲区并且不会将其内容发送给用户,从而保留隐藏ob_flush()之后的所有内容。

答案 1 :(得分:0)

如何使用file_get_contents访问脚本?你如何使用浏览器访问它?如果您在没有“http://”的情况下访问脚本,当然它永远不会被执行。使用与浏览器中相同的URL。

编辑:

即使在连接关闭之前,浏览器也会呈现页面。即使你刷新,我也不认为连接是关闭的。你可以启动Wireshark并检查。 stream_get_contents和file_get_contents将阻塞,直到它们具有所有输出。即使你脸红了,也无法确定没有更多的内容。由于内容长度标题似乎没有使{file,stream} _get_contents更早返回,因此您可能需要实现自己的缓冲,ala。 fopen,read,fclose。

答案 2 :(得分:0)

好像我做了一个非常简单的错误。由于我已经有了一个流实现,因此我无法从流中读取:D