グレースフル シャットダウン、残留オプション、ソケット クロージャ
ソケットを閉じるソケット接続をシャットダウンする対象の説明として、次の資料が提供されます。 ソケット接続のシャットダウンとソケットのクローズの違いを区別することが重要です。
ソケット接続をシャットダウンするには、2 つのエンドポイント間でプロトコル メッセージを交換する必要があります。以降はシャットダウン シーケンスと呼ばれます。 シャットダウン シーケンスの 2 つの一般的なクラスが定義されています。グレースフルとアボート (ハードとも呼ばれます)。 グレースフル シャットダウン シーケンスでは、キューに登録されているが、まだ送信されていないデータは、接続が閉じられる前に送信できます。 中止シャットダウンでは、送信されていないデータはすべて失われます。 シャットダウン シーケンスの発生 (グレースフルまたは中止) を使用して、シャットダウンが進行中であることを示すFD_CLOSEを関連付けられたアプリケーションに提供することもできます。
一方、ソケットを閉じると、ソケット ハンドルの割り当てが解除され、アプリケーションがソケットを参照したり使用したりできなくなります。
Windows ソケットでは、shutdown 関数と WSASendDisconnect 関数の両方を使用してシャットダウン シーケンスを開始できます。一方、closesocket 関数を使用してソケット ハンドルの割り当てを解除し、関連付けられているリソースを解放します。 ただし、closesocket 関数によってシャットダウン シーケンスがまだ発生していない場合に暗黙的に発生するため、混乱が生じます。 実際、この機能に依存し、closesocket を使用してシャットダウン シーケンスを開始し、ソケット ハンドルの割り当てを解除することは、かなり一般的なプログラミング手法となっています。
この使用を容易にするために、ソケット インターフェイスは、暗黙的なシャットダウン シーケンスを正常にするか中止するかをプログラマが指定できるようにするソケット オプション メカニズムを使用して制御を提供します。また、closesocket 関数を維持して (すぐには完了しません)、グレースフル シャットダウン シーケンスが完了するまでの時間を節約できます。 これらの重要な区別と、この方法で closesocket を使用することの影響は、まだ広く理解されていません。
ソケット オプションのSO_LINGERとSO_DONTLINGERに適切な値を設定することで、closesocket 関数を使用して次の種類の動作を取得できます。
- 中止シャットダウンシーケンス、closesocketからの即時リターン。
- 正常なシャットダウン。シャットダウン シーケンスが完了するか、指定された時間間隔が経過するまで戻りを遅延させます。 グレースフル シャットダウン シーケンスが完了する前に時間間隔が期限切れになると、中止シャットダウン シーケンスが発生し、closesocket返されます。
- 正常なシャットダウン、即時復帰。シャットダウン シーケンスをバックグラウンドで完了できます。 これは既定の動作ですが、アプリケーションには、正常なシャットダウン シーケンスが実際に完了したタイミング (またはかどうか) を知る方法はありません。
SO_LINGERおよびSO_DONTLINGERソケット オプションの使用と、関連する 残留 構造については、SOL_SOCKET ソケット オプションの と の残留 構造に関するリファレンス セクションで詳しく説明します。
接続の破棄中に発生する問題の可能性を最小限に抑えるために使用できる手法の 1 つは、closesocketによって開始される暗黙的なシャットダウンに依存しないようにすることです。 代わりに、シャットダウンまたは WSASendDisconnect、2 つの明示的なシャットダウン機能のいずれかを使用します。 これにより、保留中のすべてのデータが受信されたことを示すFD_CLOSE表示がピア アプリケーションによって受信されます。 これを示すために、次の表は、アプリケーションのクライアントコンポーネントとサーバーコンポーネントによって呼び出される関数を示しています。この関数は、クライアントがグレースフル シャットダウンを開始する役割を担います。
クライアント側 | サーバー側 |
---|---|
(1) シャットダウン(SD_SEND) を呼び出してセッションの終了を通知し、クライアントに送信するデータがなくなったことを示します。 | |
(2) 進行中の正常なシャットダウンとすべてのデータが受信されたことを示すFD_CLOSEを受信します。 | |
(3) 残りの応答データを送信します。 | |
(ローカルのタイミング基準値のみ)FD_READを取得し、recv呼び出して、サーバーによって送信されたすべての応答データを取得します。 | (4) シャットダウン(SD_SEND) を呼び出して、サーバーに送信するデータがないことを示します。 |
(5) FD_CLOSE表示を受け取ります。 | (ローカルのタイミング基準値のみ)closesocket呼び出します。 |
(6) closesocket呼び出します。 |