ネットワークプログラミングでは、特に長い接続を含むシナリオでは、サーバーは複数のクライアント接続を継続的に聞き、管理する必要があります。 PHPはリッチソケット機能を提供します。Socket_Accept ()は、クライアント接続要求を受信するために使用される重要な機能の1つです。この記事では、socket_accept()を使用して長い接続シナリオで効率的な接続管理を実現する方法を詳細に紹介します。
長い接続とは、クライアントがサーバーとの接続を確立した後、接続が開いたままであり、両当事者が接続が明示的に閉じられるまで通信を続けることができることを意味します。短い接続と比較して、長い接続は接続を頻繁に確立および閉じるというオーバーヘッドを減らし、インスタント通信やメッセージプッシュなどのシナリオにより適しています。
socket_accept()は、リスニングソケットからの接続要求を受け入れ、クライアントとの通信のために新しいソケットリソースを返すために使用されます。典型的な使用法は次のとおりです。
$serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($serverSocket, '0.0.0.0', 8080);
socket_listen($serverSocket);
while (true) {
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
// 取り扱いエラー
continue;
}
// クライアントリクエストを処理します
}
ブロッキングの問題
socket_accept()はブロッキングコールです。接続要求がない場合、プログラムはここで停止し、複数のクライアントの同時処理に影響します。
マルチ接続管理<br> シングルスレッドブロッキングを避けるために、複数のクライアント接続の読み取り操作を同時に管理する必要があります。
リソース職業<br> 長すぎる接続がシステムリソースを占有し、合理的なリリースとメンテナンスが必要です。
Socket_set_nonblock()を介してソケットを非ブロッキングモードに設定して、ブロッキングや接続の待機を避けます。
socket_set_nonblock($serverSocket);
この時点で、socket_accept()はブロックされず、接続要求がない場合、 falseが返されます。
socket_select()を使用すると、複数のソケットの読み取り状態を同時に聞くことができ、非ブロッキングモードと組み合わせることで、複数の長い接続を効率的に処理できます。
サンプルコード:
$serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($serverSocket, '0.0.0.0', 8080);
socket_listen($serverSocket);
socket_set_nonblock($serverSocket);
$clients = [];
while (true) {
$readSockets = $clients;
$readSockets[] = $serverSocket;
$write = $except = null;
$numChangedSockets = socket_select($readSockets, $write, $except, 0, 500000);
if ($numChangedSockets === false) {
// エラー処理
break;
} elseif ($numChangedSockets > 0) {
// 新しい接続があるかどうかを聞いてください
if (in_array($serverSocket, $readSockets)) {
$newClient = socket_accept($serverSocket);
if ($newClient !== false) {
socket_set_nonblock($newClient);
$clients[] = $newClient;
}
// 処理されたリスニングソケットを削除します
$key = array_search($serverSocket, $readSockets);
unset($readSockets[$key]);
}
// クライアントデータを処理します
foreach ($readSockets as $clientSocket) {
$data = @socket_read($clientSocket, 1024, PHP_NORMAL_READ);
if ($data === false || $data === '') {
// クライアントは接続を閉じます
$key = array_search($clientSocket, $clients);
socket_close($clientSocket);
unset($clients[$key]);
} else {
$data = trim($data);
if ($data) {
// 这里クライアントデータを処理します
socket_write($clientSocket, "サーバーが受信されました: $data\n");
}
}
}
}
// ここにハートビート検出を追加できます、タイムアウト処理およびその他のロジック
}
ハートビートメカニズム:ハートビートパケットを定期的に送信して、クライアントの生存を検出し、時間内に無効な接続を閉じます。
接続プール:リソースの疲労を避けるために、接続の最大数を制限します。
タイムアウト切断:長い間データ相互作用がない接続を閉じます。
非ブロッキングモードを設定し、 Socket_Select()多重化テクノロジーを組み合わせることにより、PHPはSocket_accept()を使用して長い接続を管理し、多数のクライアント接続の同時処理を実現できます。接続のメンテナンスとリソース管理のメカニズムを合理的に設計することで、安定したサーバーの操作を確保し、長時間接続シナリオのパフォーマンスを向上させることができます。