Win32 API 日本語リファレンス
ホームNetworking.WinSock › shutdown

shutdown

関数
ソケットの送受信を部分的または全面的に停止する。
DLLWS2_32.dll呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

// WS2_32.dll
#include <windows.h>

INT shutdown(
    SOCKET s,
    WINSOCK_SHUTDOWN_HOW how
);

パラメーター

名前方向説明
sSOCKETinsocket を識別する記述子。
howWINSOCK_SHUTDOWN_HOWin

どの種類の操作が許可されなくなるかを示すフラグ。このフラグに指定できる値は Winsock2.h ヘッダーファイルに定義されています。

意味
SD_RECEIVE
0
受信操作を無効にします。
SD_SEND
1
送信操作を無効にします。
SD_BOTH
2
送信操作と受信操作の両方を無効にします。

戻り値の型: INT

公式ドキュメント

shutdown 関数 (winsock.h) は、socket での送信または受信を無効にします。

戻り値

エラーが発生しなかった場合、 shutdown はゼロを返します。それ以外の場合は SOCKET_ERROR が返され、 WSAGetLastError を呼び出すことで具体的なエラーコードを取得できます。

エラーコード 意味
WSAECONNABORTED
タイムアウトやその他の障害により仮想回線が終了しました。この socket は使用できなくなるため、アプリケーションは socket をクローズする必要があります。

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

WSAECONNRESET
リモート側がハードクローズまたは強制クローズを実行したため、仮想回線がリセットされました。この socket は使用できなくなるため、アプリケーションは socket をクローズする必要があります。

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

WSAEINPROGRESS
ブロッキング型の Windows Sockets 1.1 呼び出しが進行中であるか、サービスプロバイダーがコールバック関数をまだ処理中です。
WSAEINVAL
how パラメーターが無効であるか、socket の種類と整合していません。たとえば、UNI_RECV 型の socket に対して SD_SEND を使用した場合などです。
WSAENETDOWN
ネットワークサブシステムに障害が発生しました。
WSAENOTCONN
socket が接続されていません。このエラーはコネクション指向の socket にのみ適用されます。
WSAENOTSOCK
注意 記述子が socket ではありません。
WSANOTINITIALISED
この関数を使用する前に、 WSAStartup の呼び出しが成功している必要があります。

解説(Remarks)

shutdown 関数は、受信、送信、またはその両方を無効にするために、あらゆる種類の socket で使用されます。

how パラメーターが SD_RECEIVE の場合、以降その socket に対する recv 関数の呼び出しは許可されません。これは下位のプロトコル層には影響しません。TCP socket の場合、受信待ちのデータがまだ socket にキューイングされているとき、または以降にデータが到着したときは、そのデータをユーザーに配信できないため接続がリセットされます。UDP socket の場合、受信データグラムは受け入れられてキューイングされます。いずれの場合も ICMP エラーパケットは生成されません。

how パラメーターが SD_SEND の場合、以降の send 関数の呼び出しは許可されません。TCP socket の場合、すべてのデータが送信され受信側によって確認応答された後に FIN が送信されます。

howSD_BOTH を設定すると、上記のとおり送信と受信の両方が無効になります。

shutdown 関数は socket をクローズしません。socket に関連付けられたリソースは、 closesocket が呼び出されるまで解放されません。

接続された socket をクローズする前にすべてのデータが送受信されたことを確実にするため、アプリケーションは closesocket を呼び出す前に shutdown を使用して接続をクローズする必要があります。リモート側がすべてのデータを送信し、グレースフルな切断を開始したことの通知を待つ方法の一つとして、次のように WSAEventSelect 関数を使用する方法があります。

  1. WSAEventSelect を呼び出して FD_CLOSE 通知を登録します。
  2. how=SD_SEND を指定して shutdown を呼び出します。
  3. FD_CLOSE を受け取ったら、 recv または WSARecv を、関数が成功で完了し受信バイト数がゼロになったことを示すまで呼び出します。SOCKET_ERROR が返された場合、グレースフルな切断はできません。
  4. closesocket を呼び出します。
リモート側がすべてのデータを送信し、グレースフルな切断を開始したことの通知を待つもう一つの方法として、オーバーラップ受信呼び出しを使用する方法があります。
  1. how=SD_SEND を指定して shutdown を呼び出します。
  2. recv または WSARecv を、関数が成功で完了し受信バイト数がゼロになったことを示すまで呼び出します。SOCKET_ERROR が返された場合、グレースフルな切断はできません。
  3. closesocket を呼び出します。
注意 shutdown 関数は、socket の SO_LINGER 設定に関わらずブロックしません。

詳細については、グレースフルシャットダウン、Linger オプション、および socket クローズのセクションを参照してください。

いったん shutdown 関数を呼び出して送信、受信、またはその両方を無効にすると、既存の socket 接続に対して送信または受信を再度有効にする方法はありません。

アプリケーションは、シャットダウンされた socket を再利用できることを前提にすべきではありません。特に、Windows Sockets プロバイダーは、シャットダウンされた socket での connect の使用をサポートする必要はありません。

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

アプリケーションが socket を再利用したい場合は、すべてのデータが送信用にキューイングされた後に切断して socket ハンドルを再利用できるように準備するために、dwFlags パラメーターに TF_DISCONNECTTF_REUSE_SOCKET を設定して TransmitFile または TransmitPackets 関数を呼び出すことができます。TransmitFile の要求が完了すると、その socket ハンドルを、AcceptExConnectEx など、接続の確立に以前使用した関数呼び出しに渡すことができます。TransmitPackets 関数が完了すると、その socket ハンドルを AcceptEx 関数に渡すことができます。

注意 socket レベルの切断は、基盤となるトランスポートの動作に左右されます。たとえば、TCP socket は TCP の TIME_WAIT 状態の影響を受ける場合があり、その結果 DisconnectExTransmitFile、または TransmitPackets の呼び出しが遅延することがあります。
注意 shutdown のようなブロッキング型の Winsock 呼び出しを発行する場合、Winsock は呼び出しが完了する前にネットワークイベントを待つ必要が生じることがあります。この状況では Winsock はアラート可能な待機を行い、これは同じスレッドでスケジュールされた非同期プロシージャ呼び出し (APC) によって中断される場合があります。同じスレッドで進行中のブロッキング型 Winsock 呼び出しを中断した APC の内部で、別のブロッキング型 Winsock 呼び出しを発行すると未定義の動作につながるため、Winsock クライアントは決してこれを試みてはなりません。

ATM に関する注意

非同期転送モード (ATM) と Windows Sockets 2 を使用する場合、接続のテアダウンに関して重要な問題があります。これらの重要な考慮事項の詳細については、 closesocket 関数リファレンスの「解説」セクション内にある「Notes for ATM」のセクションを参照してください。

Windows Phone 8: この関数は、Windows Phone 8 以降の Windows Phone ストアアプリでサポートされています。

Windows 8.1 および Windows Server 2012 R2: この関数は、Windows 8.1、Windows Server 2012 R2 以降の Windows ストアアプリでサポートされています。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// WS2_32.dll
#include <windows.h>

INT shutdown(
    SOCKET s,
    WINSOCK_SHUTDOWN_HOW how
);
[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern int shutdown(
    UIntPtr s,   // SOCKET
    int how   // WINSOCK_SHUTDOWN_HOW
);
<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function shutdown(
    s As UIntPtr,   ' SOCKET
    how As Integer   ' WINSOCK_SHUTDOWN_HOW
) As Integer
End Function
' s : SOCKET
' how : WINSOCK_SHUTDOWN_HOW
Declare PtrSafe Function shutdown Lib "ws2_32" ( _
    ByVal s As LongPtr, _
    ByVal how As Long) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

shutdown = ctypes.windll.ws2_32.shutdown
shutdown.restype = ctypes.c_int
shutdown.argtypes = [
    ctypes.c_size_t,  # s : SOCKET
    ctypes.c_int,  # how : WINSOCK_SHUTDOWN_HOW
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
shutdown = Fiddle::Function.new(
  lib['shutdown'],
  [
    Fiddle::TYPE_UINTPTR_T,  # s : SOCKET
    Fiddle::TYPE_INT,  # how : WINSOCK_SHUTDOWN_HOW
  ],
  Fiddle::TYPE_INT)
#[link(name = "ws2_32")]
extern "system" {
    fn shutdown(
        s: usize,  // SOCKET
        how: i32  // WINSOCK_SHUTDOWN_HOW
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("WS2_32.dll", SetLastError = true)]
public static extern int shutdown(UIntPtr s, int how);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_shutdown' -Namespace Win32 -PassThru
# $api::shutdown(s, how)
#uselib "WS2_32.dll"
#func global shutdown "shutdown" sptr, sptr
; shutdown s, how   ; 戻り値は stat
; s : SOCKET -> "sptr"
; how : WINSOCK_SHUTDOWN_HOW -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
#uselib "WS2_32.dll"
#cfunc global shutdown "shutdown" sptr, int
; res = shutdown(s, how)
; s : SOCKET -> "sptr"
; how : WINSOCK_SHUTDOWN_HOW -> "int"
; INT shutdown(SOCKET s, WINSOCK_SHUTDOWN_HOW how)
#uselib "WS2_32.dll"
#cfunc global shutdown "shutdown" intptr, int
; res = shutdown(s, how)
; s : SOCKET -> "intptr"
; how : WINSOCK_SHUTDOWN_HOW -> "int"
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procshutdown = ws2_32.NewProc("shutdown")
)

// s (SOCKET), how (WINSOCK_SHUTDOWN_HOW)
r1, _, err := procshutdown.Call(
	uintptr(s),
	uintptr(how),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // INT
function shutdown(
  s: NativeUInt;   // SOCKET
  how: Integer   // WINSOCK_SHUTDOWN_HOW
): Integer; stdcall;
  external 'WS2_32.dll' name 'shutdown';
result := DllCall("WS2_32\shutdown"
    , "UPtr", s   ; SOCKET
    , "Int", how   ; WINSOCK_SHUTDOWN_HOW
    , "Int")   ; return: INT
●shutdown(s, how) = DLL("WS2_32.dll", "int shutdown(int, int)")
# 呼び出し: shutdown(s, how)
# s : SOCKET -> "int"
# how : WINSOCK_SHUTDOWN_HOW -> "int"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "ws2_32" fn shutdown(
    s: usize, // SOCKET
    how: i32 // WINSOCK_SHUTDOWN_HOW
) callconv(std.os.windows.WINAPI) i32;
proc shutdown(
    s: uint,  # SOCKET
    how: int32  # WINSOCK_SHUTDOWN_HOW
): int32 {.importc: "shutdown", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
int shutdown(
    size_t s,   // SOCKET
    int how   // WINSOCK_SHUTDOWN_HOW
);
ccall((:shutdown, "WS2_32.dll"), stdcall, Int32,
      (Csize_t, Int32),
      s, how)
# s : SOCKET -> Csize_t
# how : WINSOCK_SHUTDOWN_HOW -> Int32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t shutdown(
    uintptr_t s,
    int32_t how);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.shutdown(s, how)
-- s : SOCKET
-- how : WINSOCK_SHUTDOWN_HOW
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const shutdown = lib.func('__stdcall', 'shutdown', 'int32_t', ['uintptr_t', 'int32_t']);
// shutdown(s, how)
// s : SOCKET -> 'uintptr_t'
// how : WINSOCK_SHUTDOWN_HOW -> 'int32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WS2_32.dll", {
  shutdown: { parameters: ["usize", "i32"], result: "i32" },
});
// lib.symbols.shutdown(s, how)
// s : SOCKET -> "usize"
// how : WINSOCK_SHUTDOWN_HOW -> "i32"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t shutdown(
    size_t s,
    int32_t how);
C, "WS2_32.dll");
// $ffi->shutdown(s, how);
// s : SOCKET
// how : WINSOCK_SHUTDOWN_HOW
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Ws2_32 extends StdCallLibrary {
    Ws2_32 INSTANCE = Native.load("ws2_32", Ws2_32.class);
    int shutdown(
        long s,   // SOCKET
        int how   // WINSOCK_SHUTDOWN_HOW
    );
}
@[Link("ws2_32")]
lib LibWS2_32
  fun shutdown = shutdown(
    s : LibC::SizeT,   # SOCKET
    how : Int32   # WINSOCK_SHUTDOWN_HOW
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef shutdownNative = Int32 Function(UintPtr, Int32);
typedef shutdownDart = int Function(int, int);
final shutdown = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<shutdownNative, shutdownDart>('shutdown');
// s : SOCKET -> UintPtr
// how : WINSOCK_SHUTDOWN_HOW -> Int32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function shutdown(
  s: NativeUInt;   // SOCKET
  how: Integer   // WINSOCK_SHUTDOWN_HOW
): Integer; stdcall;
  external 'WS2_32.dll' name 'shutdown';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "shutdown"
  c_shutdown :: CUIntPtr -> Int32 -> IO Int32
-- s : SOCKET -> CUIntPtr
-- how : WINSOCK_SHUTDOWN_HOW -> Int32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let shutdown =
  foreign "shutdown"
    (size_t @-> int32_t @-> returning int32_t)
(* s : SOCKET -> size_t *)
(* how : WINSOCK_SHUTDOWN_HOW -> int32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library ws2_32 (t "WS2_32.dll"))
(cffi:use-foreign-library ws2_32)

(cffi:defcfun ("shutdown" shutdown :convention :stdcall) :int32
  (s :uint64)   ; SOCKET
  (how :int32))   ; WINSOCK_SHUTDOWN_HOW
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $shutdown = Win32::API::More->new('WS2_32',
    'int shutdown(WPARAM s, int how)');
# my $ret = $shutdown->Call($s, $how);
# s : SOCKET -> WPARAM
# how : WINSOCK_SHUTDOWN_HOW -> int
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目
使用する型