Php 如何使用命名管道在fopen上设置超时
我正在尝试使用命名管道在PHP中执行一些IPC。我通过创建了一个命名管道Php 如何使用命名管道在fopen上设置超时,php,linux,ipc,fopen,Php,Linux,Ipc,Fopen,我正在尝试使用命名管道在PHP中执行一些IPC。我通过创建了一个命名管道 $pipePath = __DIR__ . '/pipe'; posix_mkfifo($pipePath, 0600); 在完成一些计算后,还有另一个进程应该写入该管道。我可以等待它完成,然后用如下方式阅读结果: $result = file_get_contents($pipePath); 还是更冗长 $in = fopen($pipePath, 'r'); $result = fread($in, 8192);
$pipePath = __DIR__ . '/pipe';
posix_mkfifo($pipePath, 0600);
在完成一些计算后,还有另一个进程应该写入该管道。我可以等待它完成,然后用如下方式阅读结果:
$result = file_get_contents($pipePath);
还是更冗长
$in = fopen($pipePath, 'r');
$result = fread($in, 8192);
fclose($in);
(我简化了第二种方法;在实际代码中,我会检查错误,在循环中运行fread
,以防结果大于8192字节,等等。)
然而,虽然另一个进程应该完成,但我不相信它会成功,所以我希望在尝试读取结果时有一个超时。在等待了一段时间后,我想放弃并报告一个错误,说它崩溃了,等等。使用给定的两种方法,PHP代码将永远挂起(或很长时间)等待写入管道的内容。具体来说,file\u-get\u-contents
和fread
将挂起
我能想出的唯一解决办法是这样的:
$timeout = 10; //seconds
for ($i = 0; $i < $timeout; $i++) {
$in = @fopen($pipePath, 'rn');
if ($in) break;
sleep(1);
}
if (!$in) {
throw new RuntimeException("The other process did not finish in the allotted time");
}
$result = fread($in, 8192);
fclose($in);
$f=fopen("my.fifo","rn");
$r=array($f);
$w=array();
$x=array();
stream_select($r,$w,$x,10);
$timeout=10//秒
对于($i=0;$i<$timeout;$i++){
$in=@fopen($pipePath,'rn');
如果($)中断;
睡眠(1);
}
如果(!$in){
抛出新的RuntimeException(“其他进程未在分配的时间内完成”);
}
$result=fread(8192美元);
fclose(美元);
这使用未记录的'n'
标志来fopen
,如上的一条注释所示。如果阻塞,则会导致fopen
调用立即失败
但是,我不喜欢此解决方案,原因有两个:
fopen
时,我可以添加一个上下文参数来指定超时值。但是,这似乎对此不起作用,设置默认套接字超时也不起作用
有没有更好的方法来处理管道?如果不是,我可能会考虑切换到UNIX套接字,但是在其他进程中,这些不太容易支持,所以我宁愿不这样做。
(仅供参考,我只关心Linux;不需要在Windows或任何其他系统上运行的东西,以防出现这种情况。)我找到了一种方法 首先,我不知道
n
标志,这是非常有用的信息
但是,如果函数阻塞,则函数失败的说法并不完全正确。它仍然返回一个文件句柄。我们可以使用文件句柄并将其传递给stream\u select
函数,以等待数据可用
大概是这样的:
$timeout = 10; //seconds
for ($i = 0; $i < $timeout; $i++) {
$in = @fopen($pipePath, 'rn');
if ($in) break;
sleep(1);
}
if (!$in) {
throw new RuntimeException("The other process did not finish in the allotted time");
}
$result = fread($in, 8192);
fclose($in);
$f=fopen("my.fifo","rn");
$r=array($f);
$w=array();
$x=array();
stream_select($r,$w,$x,10);
此代码等待10秒钟,等待其他人写入fifo的另一端。不确定我为什么没有想到使用select。我认为问题的一部分在于我的问题最初声称
fopen
会挂起,但实际上挂起的是fread
。