サーバーがハングしているかどうかをテストするには、TCP ソケットを作成し、80
IP アドレス127.0.0.1
(ループバック アドレス) のポートに接続します。次に、ソケットを介して次のテキストを送信します
GET / HTTP/1.1\r\n\r\n
ほとんどのサーバーは、それを へのリクエストとして解釈しますindex.html
。または、テスト用に文書化されていない URL を実装することもできます (これにより、より短い事前定義された応答が可能になります)。
GET /test/fdoaoqfaf12491r2h1rfda HTTP/1.1\r\n\r\n
次に、サーバーからの応答を読み取る必要があります。これにはselect
、適切なタイムアウトを指定して を使用して、サーバーからデータが返されたかどうかを判断し、返された場合は を使用recv
してデータを読み取る必要があります。サーバーからの応答は、ヘッダーとそれに続くコンテンツで構成されます。ヘッダーはテキスト行で構成され、ヘッダーの最後に空白行があります。行\r\n
は で終わるので、ヘッダーの最後は です\r\n\r\n
。
コンテンツの取得には、select
and recv
untilの呼び出しが含まれrecv
ます。これは、サーバーが応答を送信してからソケットを閉じることを前提としています。一部の高度なサーバーは、ソケットを開いたままにして、同じソケットで複数の要求を許可します。単純な組み込みサーバーはそれを行うべきではありません。(サーバーが複数のリクエストに同じソケットを使用しようとしている場合は、その機能をオフにする方法を理解する必要があります。)
これで問題ありませんが、ハングしないようにコードを書き直す必要があります。
この問題の原因として最も可能性が高いのは、サーバーに多数のダングリング ソケット (つまり、適切にクリーンアップされていないクライアントからの接続) があることです。ダングリング ソケットは、サーバーが開いている接続の数に制限があるか、サーバーを実行しているプロセスがそのファイル記述子をすべて使い果たすため、最終的にはサーバーがそれ以上の接続を受け入れることができなくなります。
最初に確認することは、TCP タイムアウト値です。私が取り組んだ 1 つのプロジェクトでは、デフォルトのタイムアウトが 5 時間でした。これは、ダングリング ソケットが 5 時間開いたままになることを意味していました。妥当なタイムアウトは 1 分です。
次に、意図的に誤動作するクライアントを作成する必要があります。クライアントは不正行為をする可能性があります
- サーバーの応答を読み取らずにソケットを開いたままにする
- 応答の読み取り中にソケットを突然閉じる
- 応答の読み取り中にソケットを正常に閉じます
最初の状況は、TCP タイムアウトによって処理する必要があります。他の 2 つは、サーバー コードで適切に処理する必要があります。ioctl
優雅で突然のソケット閉鎖は、関数の SO_LINGER オプションによって制御されshutdown
ます。クライアントが誤動作した後、サーバー プロセスで開いているファイル記述子の数を調べて、サーバーが状況を正しく処理したことを確認します。