PHPでは、 socket_accept()関数は、ソケットサーバーベースを実装する重要な機能の1つです。クライアント接続要求を受け入れるために使用され、ネットワークサービスを構築する際にクライアント接続を処理する際のコアリンクです。この記事では、socket_accept()を使用して効率的かつ並行したクライアント接続処理を実現し、サンプルコードを組み合わせて実用的なアプリケーションを表示する方法を詳細に紹介します。
socket_accept()は、リスニングされたソケットから接続されたクライアントソケットを取り出し、クライアントとの通信のために新しいソケットリソースを返します。接続がない場合は、待機をブロックします。簡単に言えば、それはサーバーがクライアント接続を受け入れるための入り口です。
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
echo "クライアント接続を受け入れると失敗しました: " . socket_strerror(socket_last_error()) . "\n";
} else {
echo "クライアント接続を正常に受け入れます\n";
}
PHP自体はシングルスレッドです。 socket_accept()を直接使用して複数の接続を処理する場合、処理が実行されない場合、サーバーは特定のクライアントでブロックされ、他の接続要求に同時に応答できなくなります。
この問題を解決するには、一般的に使用されるソリューションが次のとおりです。
マルチプロセス/マルチスレッド: PCNTL_FORK()を介して子プロセスを作成して、各クライアントを処理します。
非ブロッキングモードと多重化: Socket_Set_NonBlock()およびSocket_Select()と組み合わせて、単一のスレッドで複数の接続を投票します。
イベント駆動型フレームワーク:ReactPhpなどのサードパーティライブラリを使用して、非同期IOを実装します。
この記事では、マルチプロセスの方法に焦点を当て、 Socket_accept()を使用して同時クライアントを効率的に処理する方法を示します。
次の例は、主なプロセスが接続のリスニングと受信を担当する単純なマルチプロセスサーバーを示しており、子プロセスはクライアントのリクエストの処理を担当しています。
<?php
// 作成する TCP socket
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($server, '0.0.0.0', 8080);
socket_listen($server);
echo "サーバーの起動,ポートを聞いてください 8080...\n";
while (true) {
// クライアント接続を受け入れます(ブロック)
$client = socket_accept($server);
if ($client === false) {
echo "socket_accept 間違い: " . socket_strerror(socket_last_error()) . "\n";
continue;
}
// 作成するサブプロセス処理クライアント
$pid = pcntl_fork();
if ($pid == -1) {
echo "无法作成する子进程\n";
socket_close($client);
continue;
} elseif ($pid > 0) {
// 親プロセスはクライアント接続を閉じます,監視を続けます
socket_close($client);
// 子供のプロセスを待つか、信号処理を使用して回復することを選択できます
} else {
// サブプロセス処理クライアント
socket_close($server); // 子プロセスでリスニングソケットを閉じます
$msg = "訪問してください m66.net PHP サーバ!\n";
socket_write($client, $msg, strlen($msg));
// クライアントメッセージを読む
$input = socket_read($client, 2048);
echo "クライアントメッセージを受け取りました: $input\n";
// 単純なエコー
socket_write($client, "サーバ已收到: " . $input);
socket_close($client);
exit(0); // サブプロセス出口
}
}
Socket_Createを使用してTCPソケットを作成し、ポートをバインドしてリッスンします。
socket_accept()を使用して、クライアント接続の待機をブロックします。
PCNTL_FORK()を使用して、子プロセスを作成します。親プロセスはクライアントソケットを閉じ、聴き続けます。子プロセスは、クライアントデータの読み取りと書き込みを担当します。
ゾンビプロセスを避けるために、子プロセスが終了した後に終了します。
ゾンビプロセスを防ぐ<br> 主なプロセスは、ゾンビプロセスが蓄積されないように、 PCNTL_WAITPID()の信号処理または定期的な呼び出しを通じて子どものプロセスをリサイクルする必要があります。
非ブロッキングと多重化<br> socket_select()を使用して多重化を実装します。マルチプレックスは、プロセスオーバーヘッドを避けるために、単一のプロセスで複数のクライアントを同時に聴くことができます。
接続プール管理<br> 多数の接続の場合、接続プールとタスクキューは、サーバーの安定性を向上させるように設計できます。
エラー処理とロギング<br> 生産環境に詳細なエラー処理とログを組み込むことは、問題のトラブルシューティングに役立ちます。
socket_accept()を介してマルチプロセス法と組み合わせて、効率的な並行クライアント接続処理を実現できます。 PHP自体は、同時ネットワークプログラミングが高くなるのではありませんが、合理的な設計とシステムの呼び出しを通じてタイムリーなレスポンシブネットワークサービスを作成できます。
マルチプロセスモードはシンプルで直感的ですが、リソース消費量が高いという欠点もあることに注意する必要があります。非ブロッキングIOとイベント駆動型フレームワークを組み合わせることは、よりモダンなアプローチです。いずれにせよ、 socket_accept()は接続処理の基礎です。