stream_select
(PHP 4 >= 4.3.0, PHP 5, PHP 7)
stream_select — select() システムコールと同等の操作を、 ストリームの配列に対して tv_sec と tv_usec で指定されたタイムアウト時間をもって行う
説明
&$read
, array &$write
, array &$except
, int $tv_sec
[, int $tv_usec = 0
] ) : intstream_select() はストリームの配列を受け取ると、 それらの状態が変化するまで待ちます。機能としては、ストリームに対して 働くという点以外では socket_select() と同一です。
パラメータ
-
read -
read配列に列挙されたストリームに対しては、 何らかのデータがそのストリーム内で読み出せる状態にあるかどうか 監視が行われます (より正確にいえば、ブロックしないで読み出せる状態かどうか - 特にストリームが EOF に達したかどうか、です。このとき、 fread() は長さ 0 の文字列を返します)。 -
write -
write配列に列挙されたストリームに対しては、 ブロックしないで書き込みができるかどうかの監視が行われます。 -
except -
except配列に列挙されたストリームに対しては、 重大な例外("帯域外の")データが発生したかどうかの監視が行われます。
stream_select() のすべてのパラメータに配列を 渡す必要はありません。代わりに そのままにしておくことも、空の配列を渡すことも、注意:
stream_select() の終了時には、 どのストリームの状態が実際に変化したのかが分かるよう、 配列
read、writeおよびexceptに変更が加えられます。NULLを渡すことも できます。このとき、それらの変数は参照渡しで渡されるため、 stream_select() から戻った時点で変更されている 可能性があることに注意してください。 -
tv_sec -
tv_secとtv_usecは、一体となって、timeout パラメータを表現します。tv_secは秒数を指定し、一方tv_usecはマイクロ秒数を指定します。 timeout は、stream_select() の実行から戻るまでの時間の上限です。tv_secおよびtv_usecの両方に 0 を指定すると stream_select() はデータを待たずに一瞬で戻ります。 これは現在のストリームの状態を示します。tv_secがNULL(タイムアウトなし) の場合、 stream_select() はブロックしつづけ、調べている ストリームのひとつでイベントが発生する(あるいはシグナルがシステム コールを中断する)まで終了しません。警告タイムアウト値に 0 を指定すると、ストリームの 状態を即時に取得することが可能です。しかし、ループ内でタイムアウト 0 を指定するのは良い考えではありません。 そうすると大量の CPU 時間を消費してしまいます。
タイムアウト値を数秒にするとかなりましになります。しかし、どうしても 他のコードを同時に実行させながらチェックをする必要がある場合には、 少なくとも 200000 マイクロ秒以上のタイムアウトを 設定するようにしましょう。これであなたのスクリプトの CPU 使用量を 抑えることができます。
タイムアウト値は、あくまでも経過時間の最大値であることを覚えておきましょう。 stream_select() は、指定したストリームが使用可能に なるとすぐに結果を返します。
-
tv_usec -
tv_secの説明を参照ください。
返り値
成功した場合 stream_select() は、変更された
配列に何個のストリームリソースが格納されたかを示す数を返します。
もしタイムアウトの時間内に何も規定された事象が起こらなかった場合は
0 になることもあります。エラーの際は FALSE を返し、警告を発生させます
(システムコールが別のシグナルによって中断された場合などに起こりえます)。
例
例1 stream_select() の例
この例では、$stream1 あるいは
$stream2 のどちらかに読み込めるデータが
到達したかどうかを調べます。
タイムアウトが 0 なので、すぐに結果を返します。
<?php
/* read 配列を用意 */
$read = array($stream1, $stream2);
$write = NULL;
$except = NULL;
if (false === ($num_changed_streams = stream_select($read, $write, $except, 0))) {
/* エラー処理 */
} elseif ($num_changed_streams > 0) {
/* 少なくとも 1 つのストリームに何らかの事象が起こりました。*/
}
?>
注意
注意:
現在の Zend Engine の実装上の制約により、
NULLのような定数を この関数の参照渡しが行われるパラメータに直接指定することはできません。 代わりに一時的な変数を指定するか、一番左の変数が一時的な変数になるような 式を指定してください:<?php
$e = NULL;
stream_select($r, $w, $e, 0);
?>
注意:
エラーかどうかをチェックするには === を使ってください。 stream_select() は 0 を返すことがあるため、その場合
FALSEと == 演算子で比較するとTRUEと評価されてしまうからです:<?php
$e = NULL;
if (false === stream_select($r, $w, $e, 0)) {
echo "stream_select() に失敗しました\n";
}
?>
注意:
配列に返されたストリームに対して読み込みまたは書き込み操作を行う際に、 必ずしもあなたの希望しただけデータが読まれたり書かれたりはしないことに 注意してください。たった 1 バイトしか読み出せない場合も、書き込めない 場合もあるのです。
注意:
ストリームの中には、(zlib などのように) この関数で select できないものもあります。
注意:
Windows の互換性: Windows 98 では、 proc_open() が返すパイプに対して stream_select() を使用すると データが失われる可能性があります。
Windows では、proc_open() が返すファイル記述子に 対して stream_select() を使用すると 失敗して
FALSEを返すことがあります。
参考
- stream_set_blocking() - ストリームのブロックモードを有効にする / 解除する