PHPでは、 socket_accept()関数を使用して、クライアントの接続要求を受け入れ、クライアントとサーバーの間の通信チャネルを表す新しいソケットリソースを返します。ただし、 socket_accept()を使用する場合、不適切に処理されている場合、リソースの漏れを引き起こすのは簡単で、サーバーのパフォーマンスの低下やクラッシュさえもなります。この記事では、socket_accept()関数のリソース漏れの問題をトラブルシューティングと解決する方法について詳しく説明します。
リソースの漏れとは、プログラム操作中に適用されるシステムリソース(メモリ、ファイルハンドル、ネットワーク接続など)の障害を指し、システムリソースの消耗をもたらします。ソケットプログラミングの場合、 socket_accept()への呼び出しのたびにソケットリソースが正しく閉じられない場合、多数の未発表ソケット接続が最終的にシステムのファイル記述子に入力されます。
通信が完了したクライアントソケットは閉じられていません
socket_accept()がクライアント接続を正常に受け入れた後、 socket_close()がビジネスロジックを処理した後にクライアントソケットを閉じるために呼び出されない場合、リソースは引き続き占有されます。
異常な出口は、リソースがリリースされない<br>になります クライアントがリクエストすると、プログラムが例外を経験したり、早期に終了したり、ソケットを閉じたりするロジックに移動しない場合、リソースはリークされます。
ループで繰り返される通話ですが、古いリソースはリリースされません<br> Socket_accept()はサーバーループで常に呼び出されますが、古い接続リソースは閉じられていません。
システムファイルの記述子の使用を監視します
Linuxでは、コマンドを使用して、プロセスによって開かれたファイル記述子の数を表示できます。たとえば、:
lsof -p <pid> | wc -l
数が増え続けているかどうかを観察します。
ロギングソケットの作成と閉鎖<br> コードにログを追加し、 socket_accept()によって返されたソケットリソースと、毎回対応するシャットダウン操作を記録し、ペアで表示されるかどうかを確認します。
ツールを使用して、メモリとリソースの使用を検出します<BR> Straceなどのシステムツールの助けを借りて、システムコールを監視し、閉鎖されていないソケットを見つけます。
socket_accept()を介して取得したクライアントソケットがsocket_close()を介して呼び出す必要があります。
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
// エラー処理
} else {
// ビジネスロジックを処理します
// クライアントを閉じますsocket
socket_close($clientSocket);
}
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
// エラー処理
} else {
try {
// ビジネスロジックコード
} catch (Exception $e) {
// 例外処理
} finally {
socket_close($clientSocket);
}
}
接続の最大数またはキューイングメカニズムを設定することにより、リソースの枯渇がタイムリーに発生するのを防ぎます。
socket_accept()呼び出しがループで適切に制御されていることを確認して、迅速な繰り返しの要求の蓄積を避けます。
while (true) {
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
usleep(100000); // 待って100ミリ秒,避けるCPU高騰する
continue;
}
// ビジネス処理
socket_close($clientSocket);
}
<?php
$address = '0.0.0.0';
$port = 12345;
// 作成するsocket
$serverSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($serverSocket, $address, $port);
socket_listen($serverSocket);
echo "サーバーの起動,ポートを聞いてください $port\n";
while (true) {
$clientSocket = socket_accept($serverSocket);
if ($clientSocket === false) {
echo "接続を受け入れなかった: " . socket_strerror(socket_last_error($serverSocket)) . "\n";
usleep(100000);
continue;
}
try {
// クライアントデータをお読みください
$input = socket_read($clientSocket, 1024);
echo "クライアントデータを受信しました: $input\n";
// 応答を送信します
$response = "サーバーはデータを受信しました\n";
socket_write($clientSocket, $response);
} catch (Exception $e) {
echo "例外を処理します: " . $e->getMessage() . "\n";
} finally {
// クライアントを閉じますsocket,避ける资源泄露
socket_close($clientSocket);
}
}
socket_close($serverSocket);
?>
リソースの漏れは、特にネットワーク接続に関しては、サーバーの安定した動作に対する大きな隠れた危険です。 socket_accept()によって返されるクライアントソケットリソースは、時間内に閉じている必要があり、ビジネスロジックは、例外のために閉鎖プロセスのスキップを防ぐために例外の十分な保護を提供する必要があります。同時に、システム監視手段と組み合わせて、リソースの漏れの問題を迅速に配置して修理することができます。これらの原則に従うことによってのみ、PHPソケットサービスが長期的に安定して効率的であることを保証できます。