web-dev-qa-db-ja.com

socket.shutdown vs socket.close

最近、次のようなコードを少し見ました(もちろん、sockはソケットオブジェクトです)。

sock.shutdown(socket.SHUT_RDWR)
sock.close()

ソケットでシャットダウンを呼び出してから閉じることの正確な目的は何ですか?違いがある場合、このソケットは非ブロッキングIOに使用されています。

117
Jason Baker

説明

ソケットが不要になったら、呼び出しプログラムは、ソケット記述子にクローズサブルーチンを適用することにより、ソケットを破棄できます。クローズが行われたときに信頼できる配信ソケットにデータが関連付けられている場合、システムはデータ転送を試行し続けます。ただし、データがまだ配信されていない場合、システムはデータを破棄します。アプリケーションプログラムが保留中のデータをまったく使用しない場合、ソケットを閉じる前にシャットダウンサブルーチンを使用できます。

36
Bob Nadler

closeshutdownを呼び出すと、基になるソケットに2つの異なる効果があります。

最初に指摘することは、ソケットが基盤となるOSのリソースであり、複数のプロセスが同じ基盤となるソケットのハンドルを持つことができるということです

closeを呼び出すと、ハンドルカウントが1つ減り、ハンドルカウントがゼロに達すると、ソケットと関連する接続は通常のクローズ手順を実行します(実質的にFIN/EOFをピア)、ソケットの割り当てが解除されます。

ここで注意すべきことは、別のプロセスがまだソケットへのハンドルを持っているためにハンドルカウントがゼロにならない場合、接続閉じられず、ソケットの割り当てが解除されないことです

一方、読み取りと書き込みのためにshutdownを呼び出すと、基礎となる接続が閉じられ、ソケットへのハンドルを持つプロセスの数に関係なく、FIN/EOFがピアに送信されます。ただし、それはしないソケットの割り当てを解除するため、後でcloseを呼び出す必要があります。

223

シャットダウンとクローズの説明: グレースフルシャットダウン(msdn)

シャットダウン(あなたの場合)は、接続のもう一方の端に、ソケットからの読み取りまたはソケットへの書き込みを行う意図がこれ以上ないことを示します。次に、ソケットに関連付けられているメモリをすべて解放します。

シャットダウンを省略すると、接続が正常に閉じられるまで、ソケットがOSスタックに残る場合があります。

IMOの名前「shutdown」と「close」は誤解を招きやすく、「close」と「destroy」は違いを強調します。

18
Dale Reidy

socket Programming HOWTO( py2 / py )で言及されています

切断中

厳密に言えば、shutdownを使用する前に、ソケットでcloseを使用することになっています。 shutdownは、もう一方の端のソケットへの勧告です。渡す引数に応じて、「もう送信しませんが、まだ聞きます」または「私は聞いていません、良い馬鹿!」。ただし、ほとんどのソケットライブラリは、このエチケットの使用を怠っているプログラマーに使用されるため、通常closeshutdown(); close()と同じです。そのため、ほとんどの場合、明示的なシャットダウンは必要ありません。

...

7
mykhal

上記のこのコードは間違っていませんか?

シャットダウン呼び出しの直後に閉じる呼び出しを行うと、カーネルはすべての発信バッファーを破棄します。

http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable one needs読み取りから0が返されるまで、シャットダウンから終了まで待機します。

5
Christian

シャットダウンにはいくつかの種類があります: http://msdn.Microsoft.com/en-us/library/system.net.sockets.socket.shutdown.aspx 。 * nixも同様です。

4
Ray Tayek

Shutdown(1)、ソケットにデータを送信させない

これは

1-バッファーフラッシュ

2-奇妙なエラー検出

3-安全な保護

AからBにデータを送信する場合、Bに送信されることは保証されませんが、A osバッファーに送信されることが保証されるだけです。

Aでshutdown(1)を呼び出すことにより、Aのバッファをフラッシュし、バッファが空でない場合はエラーが発生します。つまり、データはまだピアに送信されていません

ただし、これは取り返しのつかないため、すべてのデータを完全に送信し、ピアosバッファーで少なくともそれを確認した後、それを行うことができます

2
user306166