高性能PHPサーバー側のサービスを構築する場合、マルチスレッドまたはマルチプロセスモデルを使用して、同時接続を処理する必要があることがよくあります。ソケットプログラミングは、この目標を達成するための重要な手段です。ただし、ソケット接続を処理すると、ブロッキングと非ブロッキングの設定がキーになります。 Socket_set_block()およびsocket_set_nonblock()関数は、この動作を制御するために使用できます。それらを合理的に使用すると、I/Oブロックのためにスレッドやプロセスが立ち往生するのを防ぎ、サービスの安定性と応答性が向上します。
この記事では、マルチスレッドまたはマルチプロセスのPHPサービスでsocket_set_block()関数を正しく使用する方法を紹介し、問題のブロックを避け、そのアプリケーションシナリオとベストプラクティスを特定のコード例と組み合わせて説明します。
デフォルトでは、ソケットはブロックしています。 socket_read()やsocket_accept()のような関数をブロッキングソケットに呼び出すと、読み取るデータがない場合、または新しい接続がない場合、条件が満たされるまで通話が待機します。
これは、単一スレッドモデルでは問題ではありませんが、マルチスレッドまたはマルチプロセス環境では、子供のスレッドまたは子供のプロセスが閉塞のために時間内にリソースをリリースできない場合、リソースの無駄につながる可能性があります。
非ブロッキングソケットは待機せず、すぐに返され、現在データがない場合、エラーが返されます(通常はイーガインまたはewouldblock )。エラーコードを取得して、 socket_last_error()を使用して処理できます。
socket_set_block()はソケットをブロッキングモードに設定するために使用されますが、逆関数socket_set_nonblock()は非ブロッキングモードを設定するために使用されます。
マルチスレッドまたはマルチプロセッシングでは、推奨される戦略は次のとおりです。
メインスレッドまたは親プロセスでは、リスニングソケットは非ブロッキングモードを採用してブロックを受け入れないようにします。
子のスレッドまたは子プロセスでは、単一のクライアント接続をブロッキングモードに切り替えて、完全な要求ロジックの処理を容易にすることができます。
select()とstream_select()を使用してループまたはモードでは、非ブロッキングモードを維持することをお勧めします。
socket_set_block()を正しく使用する方法を示すマルチプロセスモデルに基づいたPHPサービスの例を次に示します。
<code>&lt;?php set_time_limit(0); $ host = '0.0.0.0';
$ port = 9000;
//ソケットを作成します
$ server = socket_create(af_inet、sock_stream、sol_tcp);
socket_bind($ server、$ host、$ port);
socket_listen($ server);
socket_set_nonblock($ server); //メインソケットを非ブロッキングモードに設定します
echo "サーバーは{$ host}で開始されました:{$ port} \ n";
while(true){
$ client = @socket_accept($ server);
if ($client === false) {
usleep(100000); // 避けるCPUアイドル
continue;
}
$pid = pcntl_fork();
if ($pid == -1) {
die("Fork failed\n");
} elseif ($pid == 0) {
// サブプロセス
socket_close($server); // サブプロセス不需要监听Socket
socket_set_block($client); // クライアントのセットアップSocketブロッキングモードで
$input = socket_read($client, 1024);
$output = strtoupper(trim($input));
socket_write($client, "You said: $output\n");
socket_close($client);
exit(0);
} else {
// 親プロセス
socket_close($client); // 親プロセス不处理客户端Socket
pcntl_wait($status, WNOHANG); // 避ける僵尸进程
}
}
?>
</code>
この例では、メインプロセスでは、ノンブロッキングソケットを使用して接続を待機し、 socket_accept()ブロッキングを回避します。チャイルドプロセスでは、クライアントと相互作用するソケットをブロッキングモードに切り替えます。これにより、入力と出力の順次処理が容易になり、ロジックがよりシンプルで信頼性が高まります。
これが状態の混乱を引き起こす可能性があるため、ブロックとノンブロックを同時に交互に切り替えるように設定しないでください。責任を定義するプロセスやスレッドを管理する方が簡単です。
Select()を使用して複数の非ブロッキングソケットを聴くことは、イベント駆動型モデルに適合するより効率的な方法です。
PHPのStream_Socket_*シリーズ関数は、いくつかのシナリオでより友好的なカプセル化を提供し、Blocking動作を制御するためにStream_set_blocking()で使用することもできます。
「リソースが一時的に利用できない」などのエラーコードが表示されたときにパニックに陥らないでください。これは、非ブロッキングソケットの特徴の1つであり、論理的な再試行またはイベントポーリングを通じて解決する必要があります。
socket_set_block()とsocket_set_nonblock()の合理的な使用は、効率的なPHPネットワークサービスを構築するための鍵です。特に、マルチスレッドまたはマルチプロセス環境では、責任を明確にし、適切なブロッキングモードを設定することは、スレッド/プロセスのブロック問題を回避するだけでなく、サービスの応答速度と安定性を向上させることもできます。
上記の例と戦略を通じて、実際のプロジェクトでこれらのソケット機能をより適切に使用して、堅牢なPHPバックグラウンドサービスを作成できると思います。 <code> gitbox.net </code>のようなプライベートGitサービスまたはリアルタイム通信プラットフォームを構築している場合、正確なソケット制御は不可欠な部分です。