问题在PHP stream_select()(issue with stream_select()

2019-09-20 17:45发布

我使用stream_select(),但它返回几秒钟后0号描述符和我的功能,同时还存在要读取的数据。

一个不寻常的事情虽然是,如果你设定的超时为0,那么我总是描述符的数量为零。

$num = stream_select($read, $w, $e, 0);

Answer 1:

它是否返回数字0FALSE布尔? FALSE手段有一些错误,但零可能只是因为超时或什么有趣曾与流发生的,你应该做一个新的选择等。

我猜这可能是与零超时发生,因为它会检查并立即返回。 此外,如果你读了关于PHP手册流的选择 ,你会看到关于使用零超时这样的警告:

使用0超时值可以瞬间轮询流的状态,但是,它是不使用0超时值在一个循环中,因为它会导致你的脚本占用太多的CPU时间是个好主意。

如果这是一个TCP流,要检查连接紧密,你应该检查从返回值fread等,以确定是否其他同行已关闭了连接错误。 关于read流数组参数:

读阵列中列出的数据流会被关注,看看是否字符读取(更确切地说,看是否读不会阻塞变得可用 - 特别是流资源也准备对最终文件的-,在这种情况下,一个的fread()将返回一个零长度字符串)。



Answer 2:

stream_select()必须在一个循环中使用

stream_select()函数基本上只是民意测验你前三个参数提供的流选择,这意味着它将等到以下事件之一发生:

  • 一些数据到达
  • 或达到超时(以$ tv_sec和$ tv_usec设置)没有得到任何数据。

因此,有recieving 0作为返回值是完全正常的 ,这意味着在当前轮询周期没有新的数据。

我建议把函数在一个循环是这样的:

$EOF = false;

do {
    $tmp  = null;
    $ready = stream_select($read, $write, $excl, 0, 50000);

    if ($ready === false ) {
        // something went wrong!!
        break;
    } elseif ($ready > 0) {
        foreach($read as $r) {
            $tmp .= stream_get_contents($r);
            if (feof($r)) $EOF = true;
        }

        if (!empty($tmp)) {
            //
            // DO SOMETHING WITH DATA
            //
            continue;
        }
    } else {
        // No data in the current cycle
    }
} while(!$EOF);

请注意,在这个例子中,脚本完全从输入流忽略通通放下。 此外,“if”语句的第三部分是用于演示。



Answer 3:

http://www.php.net/stream_select

由于在当前的Zend引擎的限制,不可能通过一恒定改性剂像直接NULL作为参数传递给它期望此参数通过引用传递的功能。 代替使用一个临时变量或最左边的构件是一个临时变量的表达式:

<?php $e = NULL; stream_select($r, $w, $e, 0); ?>


Answer 4:

我有一个由底层套接字超时引起了类似的问题。

例如。 我创建了一些流

$streams = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);

然后叉,并使用一个块,如下面的

  stream_set_blocking($pipes[1], 1);
  stream_set_blocking($pipes[2], 1);
  $pipesToRead = array($pipes[1], $pipes[2]);

  while (!feof($pipesToRead[0]) || !feof($pipesToRead[1])) {
     $reads = $pipesToRead;
     $writes = null;
     $excepts = $pipesToRead;
     $tSec = null;
     stream_select($reads, $writes, $excepts, $tSec);
     // while it's generating any kind of output, duplicate it wherever it
     // needs to go
     foreach ($reads as &$read) {
        $chunk = fread($read, 8192);
        foreach ($streams as &$stream)
           fwrite($stream, $chunk);
     }
  }

粉饰什么其他的东西可能是错在那里,我的$tSec参数stream_select被忽略,而“流”,将闲置的60秒后超时并产生EOF。

如果我在创建流后添加以下

stream_set_timeout($streams[0], 999);
stream_set_timeout($streams[1], 999);

然后我得到我想要的结果,即使有更长的时间超过60秒的底层流上没有活动。

我觉得这可能是一个错误,因为我不想让底层流上60秒钟静止之后EOF,我不希望在某些任意大的值堵塞,以避免击中超时,如果我的进程空闲一段时间。

此外,即使60秒超时仍然存在,我认为它应该只是超时我stream_select()调用,我的循环应该能够继续。



文章来源: issue with stream_select() in PHP
标签: php timeout