socket.shutdownとsocket.close


122

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

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

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

回答:


38

ここに1つの説明があります:

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


241

呼び出しcloseshutdown基本的なソケットに2つの異なる効果を持っています。

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

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

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

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


すばらしい答えです。何shutdown()ができるのかわからなかったのです:)
Matt Joiner '11 / 02/11

2
読み取り用のshutdown()によってFINパケットが送信されることはありますか?つまり、shutdown(sock_fd、1);
ernesto 2014

常に.shutdown()次の電話をかけるのは賢明でしょう.close()か?それとも間に遅れがありますか?
Luc

@Luc完全にあなたがやっていることに依存します。
ロバートS.バーンズ

2
@Luc次に、他のプロセスがソケットへのハンドルを持たない限り、単に閉じるだけで問題ありません。
ロバートS.バーンズ

17

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

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

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

IMOの名前「シャットダウン」と「閉じる」は誤解を招くものであり、「閉じる」と「破棄」はそれらの違いを強調します。


それは相手に、それ以上読む意図がないことを示しません。読み取りのためのシャットダウンは、ピアに何も送信しません。
ローン侯爵

7

それはソケットプログラミングHOWTO(py2 / py3)で直接言及されています

切断しています

厳密に言うとshutdown、ソケットの前に使用する必要がありますclose。これshutdownは、反対側のソケットに対する助言です。渡す引数によっては、「もう送信しないが、引き続き聞く」、または「聞いていない、良いリダンダンス!」」。ただし、ほとんどのソケットライブラリは、このエチケットの使用を怠るプログラマが通常使用するものであるため、closeと同じshutdown(); close()です。したがって、ほとんどの場合、明示的なシャットダウンは必要ありません。

...


この情報は正しくありません。(1)プロセスをフォークして間違いなく今すぐ FINを送信したい場合または(2)両方のピアが閉じるように相互読み取りからEOSプロトコルに従事している場合にのみ、書き込み用のソケットをシャットダウンする必要があります。同時に。それ以外の場合close()は十分です。Pythonのドキュメントを修正する必要があります。
ローン侯爵

4

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

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

http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliableによると 、シャットダウンとシャットダウンの間で待機する必要があります読み取りが0を返すまで閉じます。


正しくありません。カーネルは、接続がリセットされた場合にのみ送信バッファーを破棄します。これは、ローカルアプリが既に到着した保留中の受信データをすべて読み取っていない場合、またはピアがSO_LINGERを乱していた場合に発生する可能性があります。 。スリープする必要も、閉じる前にシャットダウンを呼び出す必要もありません。この件に関しては、多くの誤った情報があります。
ローン侯爵


1

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

これは

1-バッファーフラッシング

2-奇妙なエラー検出

3-安全な防護

さらに説明します。AからBにデータを送信する場合、Bへの送信は保証されていません。Aosバッファーへの送信のみが保証されており、A osバッファーはB osバッファーに送信します。

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

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


シャットダウンはフラッシュを強制しません。バッファリングの状況は変更されていません。バッファが空でない場合、エラーは発生しません。FINは、保留中のデータの後ろにキューに入れられるだけです。答えは完全に間違っています。
ローン侯爵
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.