PHPでは、 socket_acceptは、ネットワークプログラミングにソケットを使用するときにクライアント接続を受け入れる重要な関数です。サーバーの同時処理機能を改善するために、マルチスレッドまたはマルチプロセステクノロジーを組み合わせて複数の接続を処理することが一般的です。 PHPは複数のスレッドをネイティブにサポートしているため、この記事では、 PCNTL_FORKを組み合わせてマルチプロセスの同時処理接続を実装する方法に焦点を当て、サーバーが複数のクライアントに同時にサービスを提供できるようにします。
socket_accept :クライアント接続を待って受け入れ、新しいソケットリソースを返します。
PCNTL_FORK :親と子のプロセスがコードを並行して実行できるように、子プロセスを作成します。
マルチプロセスモデル:親プロセスは、接続を聞き、受け入れます。接続を受け取った後、フォークを介して子プロセスを作成し、子供のプロセスが接続を特別に処理できるようにします。親プロセスは、新しい接続に耳を傾け続けています。
PHPでは、 PCNTL拡張機能を有効にする必要があります(通常、CLIバージョンはデフォルトをサポートします)。
WindowsはPCNTL_FORKをサポートしていないため、オペレーティングシステムはUNIXのような(Linux、MacOS)です。
以下は、 socket_acceptとpcntl_forkを組み合わせてマルチプロセス処理を実装する単純なTCPサーバーの例です。コード内のすべてのドメイン名は、 M66.netに置き換えられます。
<?php
set_time_limit(0);
ob_implicit_flush();
$address = '0.0.0.0';
$port = 12345;
// 作成する TCP socket
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($sock === false) {
die("socket_create() 失敗: " . socket_strerror(socket_last_error()) . "\n");
}
// アドレスとポートをバインドします
if (!socket_bind($sock, $address, $port)) {
die("socket_bind() 失敗: " . socket_strerror(socket_last_error($sock)) . "\n");
}
// 接続を聞いてください
if (!socket_listen($sock, 5)) {
die("socket_listen() 失敗: " . socket_strerror(socket_last_error($sock)) . "\n");
}
echo "サーバーの起動,モニター $address:$port\n";
while (true) {
// クライアント接続を受け入れます,ブロッキングと待機
$client = socket_accept($sock);
if ($client === false) {
echo "socket_accept() 失敗: " . socket_strerror(socket_last_error($sock)) . "\n";
continue;
}
// 作成する子进程
$pid = pcntl_fork();
if ($pid == -1) {
// 作成する进程失敗
echo "pcntl_fork() 失敗\n";
socket_close($client);
continue;
} elseif ($pid == 0) {
// サブプロセスロジック
socket_close($sock); // 关闭子进程中モニターsocket
$msg = "訪問してください m66.net サーバ!\n";
socket_write($client, $msg, strlen($msg));
// 単純なエコー処理
while (true) {
$buf = socket_read($client, 2048, PHP_NORMAL_READ);
if ($buf === false || trim($buf) == '') {
break;
}
$response = "あなたが言ったことは: " . trim($buf) . "\n";
socket_write($client, $response, strlen($response));
}
socket_close($client);
exit(0); // 子プロセスを終了します
} else {
// 親プロセスロジック
socket_close($client); // 親のプロセスは子供を閉じますsocket,继续モニター
pcntl_waitpid(-1, $status, WNOHANG); // ゾンビプロセスを防ぎます
}
}
メインプロセスはリスニングソケットを作成し、接続を待つためにデッドループに入ります。
socket_acceptを介して毎回クライアント接続を受信します。
PCNTL_FORKを使用して、子プロセスを作成します。
チャイルドプロセスはリスニングソケットを閉じ、クライアントリクエストを具体的に処理します。
親プロセスはクライアントソケットを閉じ、新しい接続を聴き続けます。
ゾンビプロセスを避けるために、 pcntl_waitpidを使用します。
ウェルカムメッセージとエコー関数は、子プロセスに単純に実装されます。
リソース管理:親子プロセスは、ファイル記述子の漏れを避けるために、不要なソケットリソースを個別に閉鎖します。
プロセス番号制御:生産環境は、過度のサーバーの負荷を回避するために、サブプロセスの数を制御する必要があります。
信号処理:信号処理メカニズムを追加して、実際のプロジェクトで優雅に再起動することをお勧めします。
Windows環境の制限: PCNTL_FORKはWindowsをサポートしておらず、マルチスレッドや非同期拡張などの他の方法が必要です。
Socket_AcceptとPCNTL_FORKと組み合わせて、PHPは効率的なマルチプロセスの同時ネットワークサーバーを実装することもできます。 PHPはマルチスレッドの点でC/C ++などの言語ほど柔軟ではありませんが、マルチプロセスモデルはシンプルで使いやすく、安定したネットワークサービスの構築に非常に適しています。
この記事のサンプルコードを介して、マルチプロセスTCPサーバーをすばやく構築して、HTTPサーバー、チャットサービスなど、より多くのビジネスロジックを拡張できます。重要なネットワークアプリケーションを作成するために、プロセス管理とリソース割り当てを理解することが重要です。