首页 / PHP / 如果没有数据传输,PHP流超时
如果没有数据传输,PHP流超时
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了如果没有数据传输,PHP流超时,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3253字,纯文字阅读大概需要5分钟。
内容图文
![如果没有数据传输,PHP流超时](/upload/InfoBanner/zyjiaocheng/806/7ba1c56ad26b497e89d4a6d0fc6e22b0.jpg)
我目前正在实现一个PHP类,它获取图像文件并在本地缓存它们.这些图像可能来自其他本地来源,通过HTTP或使用Guzzle客户端通过HTTP.使用PHP流包装器,我应该能够以相同的方式处理所有源.
如果没有数据通过流传输,我现在要做的就是实现超时.这应该处理以下情况:
>首先无法建立流.这可能应该在fopen调用时处理,而不是超时.
>已建立流但未传输任何数据.
>流已建立,数据已传输但在传输过程中会停止一段时间.
我想我可以用stream_set_timeout做到这一切,但我不太清楚这实际上是做什么的.如果流上的任何操作花费的时间超过允许的时间,那么超时是否适用,即我可以做一些需要0.5秒并且超时为0.75秒的事情?或者仅在没有数据通过流传输的时间超过允许时间时才适用?
我尝试使用这个简短的脚本测试行为:
<?php
$in = fopen('https://reqres.in/api/users?delay=5', 'r');
$out = fopen('out', 'w');
stream_set_timeout($in, 1);
stream_copy_to_stream($in, $out);
var_dump(stream_get_meta_data($in)['timed_out']);
虽然来自reqres.in的响应延迟了5秒,但我总是在1秒的超时时间内得到假.请有人解释一下吗?
解决方法:
我建议您使用file_get_contents和file_put_contents而不是流,它们支持所有包装器,您可以将上下文传递给它们,就像您可以fopen一样.它们通常更容易使用,因为它们返回并接受字符串而不是流.话虽这么说,我不知道你的缓存机制的性质,如果流更适合你的用例,更多的权力给你:)
问题
这里的问题似乎是误解了fopen如何在阻塞模式下使用http流包装器(在我试用之前我还没有完全理解).对于GET(the default),fopen似乎在调用时执行HTTP请求,而不是在读取流时.这可以解释为什么stream_set_timeout不能按预期运行,因为它在调用fopen后修改了流上下文.
解决方案
值得庆幸的是,有一种方法可以在调用fopen之前修改超时,而不是;你可以用上下文调用fopen.将从stream_context_create(作为Sammitch链接)返回的上下文传递给所有三种情况的fopen超时.作为参考,这是您的脚本将被修改的方式:
<?php
$ctx = stream_context_create(['http' => [
'timeout' => 1.0,
]]);
$in = fopen('https://reqres.in/api/users?delay=5', 'r', false, $ctx);
$out = STDOUT;
stream_copy_to_stream($in, $out);
var_dump(stream_get_meta_data($in)['timed_out']);
fclose($in);
注意:我假设您打算将流复制到stdout而不是“out”,这不是我平台上的有效流(Darwin).我还在脚本结尾处输入了流,这总是很好的做法.
这将创建一个超时为1的流,从调用fopen时开始.现在来测试你的三个条件.
验证行为
- The stream cannot be established in the first place. This should probably be handled at the fopen call and not with a timeout.
这样可以正常工作 – 如果无法建立连接(服务器脱机等),fopen调用会立即触发警告.只需将脚本指向localhost上的任意端口,即没有任何内容正在侦听.请注意,如果未成功建立连接,则fopen返回false.您必须在代码中检查它,以避免将false用作流.
- The stream is established but no data is transferred.
此方案也可以,只需使用普通URL运行脚本即可.这也使fopen返回false并触发警告(另一个).
- The stream is established, data is transferred but it stops some time during transfer.
这是一个有趣的案例.要测试这个,你可以编写一个脚本,发送Content-Length和其他一些标题以及一些部分数据,然后等到超时,即:
<?php
header('Content-Type: text/plain');
header('Content-Length: 10');
echo "hi";
ob_flush();
sleep(10);
ob_flush是使PHP在睡眠和脚本退出之前写入输出(不关闭连接)所必需的.您可以使用php -S localhost:port来提供此服务,然后将其他脚本指向localhost:port.在这种情况下,客户端脚本不会发出警告,并且fopen实际上将元数据集中的timed_out返回为true.
结论
stream_set_timeout不能与HTTP GET请求一起使用,并且在阻塞模式下fopen,因为fopen在调用时执行请求而不是等待读取操作.您可以通过超时将上下文传递给fopen以解决此问题.
内容总结
以上是互联网集市为您收集整理的如果没有数据传输,PHP流超时全部内容,希望文章能够帮你解决如果没有数据传输,PHP流超时所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。