【PHP8.x】stream_select関数の使い方

stream_select関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

『stream_select関数は、指定されたストリームの配列を監視し、いずれかのストリームの状態が変化するまで待機する処理を実行する関数です。この関数は、主にネットワークソケットのような複数のI/Oリソースを同時に、かつ効率的に扱うために使用されます。例えば、複数のクライアントからの接続を同時に待ち受けるサーバープログラムなどで役立ちます。一つの処理の完了を待つことで他の処理が停止してしまう「ブロッキング」を防ぎ、応答性の高いアプリケーションを構築できます。関数には、読み込みを監視するストリームの配列、書き込みを監視するストリームの配列、例外を監視するストリームの配列、そしてタイムアウト時間を指定します。指定したストリームのいずれかでデータの読み込みや書き込みが可能になるか、あるいはタイムアウトすると、関数は処理を返します。その際、引数で渡された配列の中身は、実際に状態が変化したストリームのみを含むように書き換えられます。これにより、どのストリームに対して次の操作を行うべきかを判別できます。戻り値は状態が変化したストリームの総数で、タイムアウトした場合は0が返されます。

構文(syntax)

1stream_select(?array &$read, ?array &$write, ?array &$except, ?int $seconds, int $microseconds = 0): int|false

引数(parameters)

?array &$read, ?array &$write, ?array &$except, ?int $seconds, ?int $microseconds = null

  • array &$read: 読み込みを監視するストリームの配列
  • array &$write: 書き込みを監視するストリームの配列
  • array &$except: 例外を監視するストリームの配列
  • int $seconds: タイムアウトまでの秒数
  • int $microseconds: タイムアウトまでのマイクロ秒数

戻り値(return)

int|false

現在、選択可能なストリーム(読み取り、書き込み、または例外)の数が返されます。タイムアウトが発生し、何も選択されなかった場合は 0 が返されます。エラーが発生した場合は false が返されます。

サンプルコード

PHP stream_select でストリームを監視する

1<?php
2
3/**
4 * stream_select の使用例
5 */
6
7// 読み込みを監視するストリームの配列
8$read_streams = [STDIN]; // 標準入力
9
10// 書き込みを監視するストリームの配列
11$write_streams = [];
12
13// 例外を監視するストリームの配列
14$except_streams = [];
15
16// タイムアウト: 5秒
17$seconds = 5;
18
19// タイムアウト: 0マイクロ秒
20$microseconds = 0;
21
22// ストリームを監視
23$num_changed_streams = stream_select($read_streams, $write_streams, $except_streams, $seconds, $microseconds);
24
25if ($num_changed_streams === false) {
26    // エラーが発生した場合
27    echo "stream_select() failed\n";
28} elseif ($num_changed_streams > 0) {
29    // 少なくとも1つのストリームが準備完了になった場合
30    echo "ストリームが利用可能になりました。\n";
31
32    // 読み込み可能になったストリームを処理
33    if (in_array(STDIN, $read_streams, true)) {
34        $input = fgets(STDIN); // 標準入力から1行読み込む
35        echo "入力: " . $input;
36    }
37} else {
38    // タイムアウトした場合
39    echo "タイムアウトしました。\n";
40}
41
42?>

このサンプルコードは、PHPのstream_select関数を使用して、複数のストリーム(ここでは標準入力)の状態を監視する方法を示しています。stream_select関数は、指定されたストリームの配列のうち、読み込み、書き込み、または例外の発生に対して準備ができたストリームの数を返します。

引数には、監視対象のストリームを格納した配列を渡します。$readには読み込みを監視するストリームの配列、$writeには書き込みを監視するストリームの配列、$exceptには例外を監視するストリームの配列をそれぞれ指定します。ここでは、標準入力STDINを読み込み対象として監視しています。

また、タイムアウト時間を秒単位で$seconds、マイクロ秒単位で$microsecondsとして指定します。タイムアウト時間を設定することで、指定時間内にストリームが利用可能にならなかった場合に処理を中断できます。

stream_select関数は、準備完了となったストリームの数を整数値で返します。エラーが発生した場合はfalseを返します。戻り値が0より大きい場合は、少なくとも1つのストリームが利用可能になったことを意味します。サンプルコードでは、標準入力が利用可能になった場合、fgets関数を使用して標準入力から1行読み込み、その内容を表示しています。タイムアウトした場合は、タイムアウトメッセージを表示します。

この例では標準入力のみを監視していますが、ソケット通信など、複数のストリームを同時に監視する必要がある場合に、stream_select関数は非常に有効です。

stream_select関数は、複数のストリームの状態を監視する際に使用します。引数の $read, $write, $except は、監視したいストリームを配列で指定しますが、関数実行後に状態が変化したストリームのみが残る点に注意が必要です。元の配列を保持したい場合は、コピーを渡しましょう。

タイムアウトは秒とマイクロ秒で指定します。null を指定すると、無期限に待ちます。戻り値が false の場合はエラーが発生しています。0 の場合はタイムアウトです。正の整数の場合は、状態が変化したストリームの数を示します。

サンプルコードでは標準入力(STDIN)を監視しています。in_array関数で $read_streams に STDIN が含まれているかを確認してから fgets で読み込むことで、安全に処理できます。本番環境では、外部からの入力に対してサニタイズ処理を必ず行ってください。

関連コンテンツ