【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 で読み込むことで、安全に処理できます。本番環境では、外部からの入力に対してサニタイズ処理を必ず行ってください。