shutdown

shutdown関数はソケットの送信または受信の機能を停止させます。

int shutdown(
    SOCKET s,
    int    how
);

WS2_32.DLL

引数

s

ソケットを識別するディスクリプタを指定します。

how

どの操作をこれ以上行わせないようにするかを表すフラグを指定します。このフラグに指定可能な値を以下に示します。

0 (SD_RECEIVE)
受信操作をシャットダウンします。
1 (SD_SEND)
送信操作をシャットダウンします。
2 (SD_BOTH)
送信操作および受信操作の両方をシャットダウンします。

戻り値

成功すると0を返します。

失敗すると-1 (SOCKET_ERROR) を返します。特定のエラーコードを取得するにはWSAGetLastError関数を呼び出します。

10053 (WSAECONNABORTED)

仮想通信路がタイムアウトまたは他のエラーにより終了しました。そのソケットはもはや使用することができないので、アプリケーションはソケットをクローズするべきです。

このエラーはコネクション指向ソケットにのみ適用されます。

10054 (WSAECONNRESET)

リモート側がhardクローズまたはabortiveクローズを実行したことにより、仮想通信路がリセットされました。そのソケットはもはや使用することができないので、アプリケーションはソケットをクローズするべきです。

このエラーはコネクション指向ソケットにのみ適用されます。

10036 (WSAEINPROGRESS)

ブロッキングWindows Sockets 1.1呼び出しが実行中であるか、サービスプロバイダがコールバック関数を実行中です。

10104 (WSAEINVAL)

howパラメータが有効ではないか、ソケットタイプと一致しません。例えば、UNI_RECVソケットタイプに対してSD_SENDが使用されました。

10050 (WSAENETDOWN)

ネットワークサブシステムが失敗しました。

10104 (WSAEINVAL)

ソケットが接続されていません。のエラーはコネクション指向ソケットにのみ適用されます。

10038 (WSAENOTSOCK)

指定されたディスクリプタはソケットではありません。

10093 (WSANOTINITIALISED)

この関数を呼び出す前にWSAStartup関数の呼び出しが成功していなければなりません。

解説

shutdown関数は、受信、送信、またはその両方を無効化するために、すべての種類のソケットに対して使用されます。

howパラメータがSD_RECEIVEの場合、これ以降にそのソケットに対してのrecvの呼び出しが拒否されます。これは下位のプロトコル層には何ら影響を与えません。TCPソケットでは、ソケットのキューに格納されている受信待機中のデータがまだ存在する場合、または以降にデータが到着する場合、データがユーザに到達しなかったため、接続がリセットされます。UDPソケットでは、外部からのダイアグラムが受信されキューに格納されます。どの場合においても、ICMPエラーパケットは発生しません。

howパラメータがSD_SENDの場合、これ以降にそのソケットに対してのsendの呼び出しが拒否されます。TCPソケットでは、すべてのデータが送信された後でFINが送信され、受信側により肯定応答が返されます。

howSD_BOTHを設定すると、送信と受信の両方が上記のように無効化されます。

shutdown関数はソケットをクローズしません。ソケットに割り当てられているすべてのリソースは、closesocket関数を呼び出すまで解放されません。

接続されたソケットがクローズされる前にそのソケット上ですべてのデータを確実に送受信するために、アプリケーションはclosesocketを呼び出す前にshutdown関数を使用して接続をクローズするべきです。リモート端末がすべてのデータの送信を完了しgracefulな切断を開始したことを示す通知を待機する1つの方法は、WSAEventSelect関数を以下のように使用します。

  1. WSAEventSelectを呼び出してFD_CLOSEの通知登録を行います。
  2. howSD_SENDを指定してshutdownを呼び出します。
  3. FD_CLOSE通知を受け取った際に、recvまたはWSARecvを、関数が成功してゼロバイトが受信されたことを示すまで呼び出します。SOCKET_ERRORが返された場合は、gracefulな切断を行うことはできません。
  4. closesocketを呼び出します。

リモート端末がすべてのデータの送信を完了しgracefulな切断を開始したことを示す通知を待機するもう1つの方法は、以下のように重複した受信呼び出しを行います。

  1. howSD_SENDを指定してshutdownを呼び出します。
  2. recvまたはWSARecvを、関数が成功してゼロバイトが受信されたことを示すまで呼び出します。SOCKET_ERRORが返された場合は、gracefulな切断を行うことはできません。
  3. closesocketを呼び出します。

Note: ソケットのSO_LINGERオプションの設定に関わらず、shutdownはブロックしません。

いったんshutdownを呼び出して送信、受信、またはその両方を停止させると、現在のソケット接続に対して送信や受信を再有効化する方法はありません。

アプリケーションは、ソケットがシャットダウンされた後でそのソケットを再使用できるとあてにするべきではありません。特に、シャットダウンされたソケットに対するconnectの使用のサポートは、Windows Socketsプロバイダに対して要求されていません。

アプリケーションがソケットを再使用する必要がある場合は、dwFlagsパラメータにTF_REUSE_SOCKETを指定してDisconnectEx関数を呼び出すことで、ソケットの接続をクローズしてソケットハンドルを再使用できるようにする必要があります。DisconnectEx要求が完了すると、そのソケットハンドルをAcceptExまたはConnectEx関数に渡すことができるようになります。

アプリケーションがソケットを再使用する必要がある場合は、dwFlagsパラメータにTF_DISCONNECTおよびTF_REUSE_SOCKETを指定してTransmitFileまたはTransmitPackets関数を呼び出すことで、すべてのデータが送信のためにキューに入れられた後で切断し、ソケットを再使用できるようにすることができます。TransmitFile要求が完了すると、以前に接続を確立するために使用した関数呼び出し(AcceptExまたはConnectExなど)にそのソケットハンドルを渡すことができます。TransmitPackets関数が完了すると、そのソケットハンドルをAcceptEx関数に渡すことができます。

Note: shutdownなどのブロッキングWinsock関数を呼び出す場合、Winsockは呼び出しが完了する前にネットワークイベントの待機を必要とする場合があります。そのような状況ではWinsockはアラート可能な待機を行いますが、この待機中に、同じスレッドでスケジューリングされている非同期プロシージャコール(APC)による割り込み処理が行われる可能性があります。あるブロッキングWinsock呼び出し中にAPC割り込みが発生し、その中で別のブロッキングWinsock呼び出しを行うと未定義の動作を引き起こします。そのため、Winsockクライアントはこのような呼び出しをしようとしてはいけません。

ATMに関する注意

Windows Sockets 2で非同期転送モード(ATM)を使用する際に留意しておかなければならない、接続終了に関する重要な事項があります。これに関する情報は、closesocket関数のリファレンスの解説にて「ATMに関する注意」と記載された項を参照してください。