如何通过stream_get_contents()连续监听多个TCP流?

P K*_*P K 2 php sockets streaming network-programming stream

默认stream_get_contents等待并听60秒.如果我有多个流,并希望不断听取所有流.

在foreach里面,如果我正在听一个流,我不能听其他人.

什么是连续监听和捕获所有流的流输出的解决方案?

while(true){
   //$streamArray is an array of streams obtained by stream_socket_client("tcp://..);
   foreach($streamArray as $stream){
        fputs($stream,$command);
        stream_get_contents($stream);  // and update file/DB (Blocking call)
        }
    }
Run Code Online (Sandbox Code Playgroud)

注意:对于我已经完成的每一个流 stream_set_blocking( $stream , true );

更新:

我的要求是在30分钟内听一下所有的流.同时我不能听2流.如果我有5个流,我的代码只是time division multiplexing,在30 分钟内,每个单独的流将仅记录6分钟

我有一个解决方案,可以为各个流提供AJAX请求并独立记录.当然我不想做这个多AJAX调用方法,因为它会导致更多的代码以及更多的CPU.

Kai*_*aii 6

stream_set_blocking($resource, true)同步开始读取流,这意味着每次调用都会fread()等待,直到有数据要读取.然后调用stream_get_contents(),从阻塞流中读取,直到达到EOF(关闭).结果是您逐个读取一个流而不是"同时".

以这种方式读取流是常见的并且最容易编码,但是当您想要同时处理多个流时,您必须自己处理缓冲区,定时和"流结束"检测.使用当前代码,此部分将通过阻塞流和抽象而被抽象出来stream_get_contents().

要同时读取多个流,您应该重写代码以异步读取流.

未经测试的伪示例:

// $streamArray is an array of streams obtained by stream_socket_client("..");

$buffers = array();
$num_streams = 0;
foreach($streamArray as $stream) {
    // set streams non-blocking for asynchroneous reading
    stream_set_blocking($stream, false);
    // write command to all streams - multiplexing
    fputs($stream, $command);
    // initialize buffers
    $buffers[$stream] = '';
    $num_streams++;
}
while($num_streams) {
    // use stream_select() to wait for new data and not use CPU at 100%.
    // note that the stream arrays are passed by reference and are modified
    // by stream_select() to reflect which streams are modified / have a
    // new event. Because of this we use a copy of the original stream array.
    // also note that due to a limitation in ZE you can not pass NULL directly
    // for more info: read the manual
    $no_stream = NULL;
    $select_read = $streamArray;
    stream_select($select_read, $no_stream, $no_stream, null);

    // if there is new data, read into the buffer(s)
    foreach($select_read as $stream) {
        $buffers[$stream] .= fread($stream, 4096);
        // check if the stream reached end
        if (feof($stream)) {
            $key = array_search($stream, $streamArray);
            // close stream properly
            $num_streams--;
            fclose($stream);
            // remove stream from array of open streams
            unset($streamArray[$key]);
        }
    }
}
// do something with your buffers - our use them inside the while() loop already
print_r($buffers);
Run Code Online (Sandbox Code Playgroud)