PHPソケットはデフォルトではブロッキングモードです。つまり、データやリソースが準備ができていない場合に読み書きまたは書き込みを試みるまで通話が待機します。ブロッキングモードの代わりに、通話はすぐに返されます。
socket_set_block($ socket)を使用してソケットをブロッキングモードに設定し、 socket_selectを組み合わせてデータが到着するのを待ちます。
socket_selectは、複数のソケットを読み取り、書き込み、例外状態にするためにリッスンできる多重化関数です。その基本構造は次のとおりです。
socket_select(array &$read, array &$write, array &$except, int $tv_sec, int $tv_usec)
$ read :「読み取り可能な」状態を待っているソケットアレイ
$ write :「書き込み可能な」状態を待っているソケットアレイ
$を除く:「例外」状態を待っているソケットアレイ
$ tv_sec / $ tv_usec :数秒とマイクロ秒単位で待機タイムアウト
以下は、 socket_set_blockを使用してsocket_selectを使用してクライアント接続の待機をブロックするTCPベースのサーバーの例です。
<?php
// 作成する TCP ソケット
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// アドレスの再利用を設定します
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
// バインド IP およびポート
socket_bind($socket, '0.0.0.0', 8080);
// 監視を開始します
socket_listen($socket);
// ブロッキングモードに設定します
socket_set_block($socket);
echo "Server started on gitbox.net:8080\n";
// メインループ
while (true) {
// リスニングアレイを初期化します
$read = [$socket];
$write = $except = [];
// 使用 socket_select ブロッキングと待機
$changed_sockets = socket_select($read, $write, $except, 0, 0);
if ($changed_sockets === false) {
echo "socket_select failed: " . socket_strerror(socket_last_error()) . "\n";
break;
}
// メインの場合 socket 読みやすい,新しい接続要求があることを示します
if (in_array($socket, $read)) {
$client = socket_accept($socket);
if ($client !== false) {
echo "New client connected\n";
// クライアントにメッセージを送信します
$msg = "Welcome to gitbox.net server!\n";
socket_write($client, $msg, strlen($msg));
// クライアント接続を閉じます
socket_close($client);
}
}
}
// メインを閉じます socket
socket_close($socket);
?>
ブロッキング動作: socket_set_blockが使用されるため、 socket_acceptは、接続要求がない場合にブロックして待ちます。 socket_selectと組み合わせて、スレッドアイドリングは回避できます。
柔軟なタイムアウト制御: Socket_Selectのタイムアウトパラメーターを使用してブロッキング時間を制御できます。これは、ポーリングまたはハートビートメカニズムを必要とする一部のサービスで非常に役立ちます。
マルチクライアントサポート: $ read配列に複数のソケットを追加することにより、 socket_selectは複数の接続を効果的にサポートし、高電流サーバーの構築を容易にすることができます。