私は最近、次のようなコードを少し見ました (もちろん、sock はソケット オブジェクトです)。
sock.shutdown(socket.SHUT_RDWR)
sock.close()
ソケットでシャットダウンを呼び出してから閉じる目的は何ですか? 違いがある場合、このソケットはノンブロッキング IO に使用されています。
私は最近、次のようなコードを少し見ました (もちろん、sock はソケット オブジェクトです)。
sock.shutdown(socket.SHUT_RDWR)
sock.close()
ソケットでシャットダウンを呼び出してから閉じる目的は何ですか? 違いがある場合、このソケットはノンブロッキング IO に使用されています。
呼び出しclose
てshutdown
、基になるソケットに2つの異なる影響を与えます。
最初に指摘することは、ソケットは基盤となるOSのリソースであり、複数のプロセスが同じ基盤となるソケットのハンドルを持つことができるということです。
これを呼び出すclose
と、ハンドル数が1つ減り、ハンドル数がゼロに達した場合、ソケットと関連する接続は通常のクローズ手順(事実上FIN / EOFをピアに送信)を経て、ソケットの割り当てが解除されます。
ここで注意しなければならないのは、別のプロセスがまだソケットへのハンドルを持っているためにハンドル数がゼロに達しない場合、接続は閉じられず、ソケットの割り当てが解除されないということです。
一方shutdown
、読み取りと書き込みを呼び出すと、基になる接続が閉じられ、ソケットへのハンドルを持つプロセスの数に関係なく、FIN/EOFがピアに送信されます。ただし、ソケットの割り当てが解除されることはなく、後でcloseを呼び出す必要があります。
ここに1つの説明があります:
ソケットが不要になると、呼び出し側プログラムは、ソケット記述子にcloseサブルーチンを適用することにより、ソケットを破棄できます。クローズが発生したときに信頼できる配信ソケットにデータが関連付けられている場合、システムは引き続きデータ転送を試みます。ただし、データがまだ配信されていない場合、システムはデータを破棄します。アプリケーションプログラムが保留中のデータを使用しない場合は、ソケットを閉じる前に、ソケットのシャットダウンサブルーチンを使用できます。
シャットダウンとクローズの説明:グレースフル シャットダウン (msdn)
シャットダウン(あなたの場合)は、接続の反対側に、ソケットからの読み取りまたはソケットへの書き込みの意図がないことを示します。次に、ソケットに関連付けられているすべてのメモリを解放します。
shutdown を省略すると、接続が正常に閉じられるまで、ソケットが OS スタックに残る可能性があります。
IMO では、「shutdown」と「close」という名前は誤解を招きやすく、「close」と「destroy」はそれらの違いを強調します。
Socket Programming HOWTO ( py2 / py3 ) に記載されています
切断中
厳密に言えば、
shutdown
その前にソケットで使用することになってclose
います。これshutdown
は、反対側のソケットへの通知です。渡す引数に応じて、"<em>もう送信しませんが、まだリッスンします" または "<em>リッスンしていません。よくやった!" という意味になります。close
ただし、ほとんどのソケット ライブラリは、通常 aが と同じであるこのエチケットの使用を無視するプログラマーに慣れすぎていshutdown(); close()
ます。したがって、ほとんどの場合、明示的なシャットダウンは必要ありません。...
上記のコードは間違っていませんか?
shutdown 呼び出しの直後に close 呼び出しを行うと、カーネルはいずれにせよすべての送信バッファーを破棄する可能性があります。
http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliableによると 、シャットダウンとread が 0 を返すまで閉じます。
シャットダウンにはいくつかの種類があります: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.shutdown.aspx。*nixも同様です。
Shutdown(1)、これ以上データを送信しないようにソケットを強制します
これはで便利です
1-バッファフラッシング
2-奇妙なエラー検出
3-安全な保護
詳細を説明します。AからBにデータを送信する場合、データはBに送信されることが保証されていません。データは、A osバッファーに送信されることが保証されているだけであり、AosバッファーがBosバッファーに送信されます。
したがって、Aでshutdown(1)を呼び出すと、Aのバッファがフラッシュされ、バッファが空でない場合、つまりデータがまだピアに送信されていない場合にエラーが発生します。
ただし、これは元に戻せないため、すべてのデータを完全に送信し、少なくともピアOSバッファで確実に送信した後で行うことができます。