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

WSARecvDisconnect

関数
切断時に相手からの終了データを受信する。
DLLWS2_32.dll呼出規約winapiSetLastErrorあり対応OSWindows 2000 以降

シグネチャ

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

INT WSARecvDisconnect(
    SOCKET s,
    WSABUF* lpInboundDisconnectData   // optional
);

パラメーター

名前方向説明
sSOCKETinソケットを識別する記述子。
lpInboundDisconnectDataWSABUF*inoptional受信する切断データへのポインター。

戻り値の型: INT

公式ドキュメント

WSARecvDisconnect 関数は、ソケットでの受信を終了し、ソケットがコネクション指向の場合は切断データを取得します。

戻り値

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

エラーコード 意味
WSANOTINITIALISED
この関数を使用する前に、 WSAStartup の呼び出しが成功している必要があります。
WSAENETDOWN
ネットワークサブシステムに障害が発生しました。
WSAEFAULT
lpInboundDisconnectData パラメーターが参照するバッファーが小さすぎます。
WSAENOPROTOOPT
指定されたプロトコルファミリでは切断データがサポートされていません。切断データをサポートしない TCP/IP の実装は、WSAENOPROTOOPT エラーコードを返す必要はないことに注意してください。Microsoft による TCP/IP の実装については、解説のセクションを参照してください。
WSAEINPROGRESS
ブロッキング型の Windows Sockets 1.1 呼び出しが進行中であるか、サービスプロバイダーがコールバック関数を処理中です。
WSAENOTCONN
ソケットが接続されていません(コネクション指向のソケットのみ)。
WSAENOTSOCK
記述子がソケットではありません。

解説(Remarks)

WSARecvDisconnect 関数は、コネクション指向のソケットで受信を無効にし、リモート側からの切断データを取得するために使用されます。これは shutdown (SD_RECEIVE) と同等ですが、 WSARecvDisconnect では(対応するプロトコルにおいて)切断データの受信も可能である点が異なります。

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

注意 Windows における TCP/IP のネイティブ実装は、切断データをサポートしていません。切断データは、 WSAPROTOCOL_INFO 構造体に XP1_DISCONNECT_DATA フラグを持つ Windows Sockets プロバイダーでのみサポートされます。インストールされているすべてのプロバイダーの WSAPROTOCOL_INFO 構造体を取得するには、 WSAEnumProtocols 関数を使用してください。
受信する切断データを正常に受け取るには、アプリケーションは回線が閉じられたことを判断するために別のメカニズムを使用する必要があります。たとえば、アプリケーションは FD_CLOSE 通知を受け取る、戻り値 0 を受け取る、または recv/WSARecv から WSAEDISCON または WSAECONNRESET エラーコードを受け取る必要があります。

WSARecvDisconnect 関数はソケットをクローズせず、ソケットに付随するリソースは closesocket が呼び出されるまで解放されません。

WSARecvDisconnect 関数は、ソケットの SO_LINGER 設定に関係なくブロックしません。

アプリケーションは、 WSARecvDisconnect を使用して切断したソケットを再利用できることを前提としてはなりません。特に、Windows Sockets プロバイダーは、そのようなソケットでの connect または WSAConnect の使用をサポートする必要はありません。

注意 WSARecvDisconnect のようなブロッキング型の Winsock 呼び出しを発行する場合、呼び出しを完了する前に Winsock がネットワークイベントを待つ必要があることがあります。この状況では Winsock は警告可能 (alertable) な待機を実行し、同じスレッドでスケジュールされた非同期プロシージャ呼び出し (APC) によって中断される可能性があります。同じスレッドで進行中のブロッキング型 Winsock 呼び出しを中断した APC の内部で別のブロッキング型 Winsock 呼び出しを発行すると、未定義の動作につながるため、Winsock クライアントは決して試みてはなりません。
出典・ライセンス: 上記「公式ドキュメント」の内容は 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 WSARecvDisconnect(
    SOCKET s,
    WSABUF* lpInboundDisconnectData   // optional
);
[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern int WSARecvDisconnect(
    UIntPtr s,   // SOCKET
    IntPtr lpInboundDisconnectData   // WSABUF* optional
);
<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WSARecvDisconnect(
    s As UIntPtr,   ' SOCKET
    lpInboundDisconnectData As IntPtr   ' WSABUF* optional
) As Integer
End Function
' s : SOCKET
' lpInboundDisconnectData : WSABUF* optional
Declare PtrSafe Function WSARecvDisconnect Lib "ws2_32" ( _
    ByVal s As LongPtr, _
    ByVal lpInboundDisconnectData As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

WSARecvDisconnect = ctypes.windll.ws2_32.WSARecvDisconnect
WSARecvDisconnect.restype = ctypes.c_int
WSARecvDisconnect.argtypes = [
    ctypes.c_size_t,  # s : SOCKET
    ctypes.c_void_p,  # lpInboundDisconnectData : WSABUF* optional
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
WSARecvDisconnect = Fiddle::Function.new(
  lib['WSARecvDisconnect'],
  [
    Fiddle::TYPE_UINTPTR_T,  # s : SOCKET
    Fiddle::TYPE_VOIDP,  # lpInboundDisconnectData : WSABUF* optional
  ],
  Fiddle::TYPE_INT)
#[link(name = "ws2_32")]
extern "system" {
    fn WSARecvDisconnect(
        s: usize,  // SOCKET
        lpInboundDisconnectData: *mut WSABUF  // WSABUF* optional
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("WS2_32.dll", SetLastError = true)]
public static extern int WSARecvDisconnect(UIntPtr s, IntPtr lpInboundDisconnectData);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_WSARecvDisconnect' -Namespace Win32 -PassThru
# $api::WSARecvDisconnect(s, lpInboundDisconnectData)
#uselib "WS2_32.dll"
#func global WSARecvDisconnect "WSARecvDisconnect" sptr, sptr
; WSARecvDisconnect s, varptr(lpInboundDisconnectData)   ; 戻り値は stat
; s : SOCKET -> "sptr"
; lpInboundDisconnectData : WSABUF* optional -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "WS2_32.dll"
#cfunc global WSARecvDisconnect "WSARecvDisconnect" sptr, var
; res = WSARecvDisconnect(s, lpInboundDisconnectData)
; s : SOCKET -> "sptr"
; lpInboundDisconnectData : WSABUF* optional -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; INT WSARecvDisconnect(SOCKET s, WSABUF* lpInboundDisconnectData)
#uselib "WS2_32.dll"
#cfunc global WSARecvDisconnect "WSARecvDisconnect" intptr, var
; res = WSARecvDisconnect(s, lpInboundDisconnectData)
; s : SOCKET -> "intptr"
; lpInboundDisconnectData : WSABUF* optional -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procWSARecvDisconnect = ws2_32.NewProc("WSARecvDisconnect")
)

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

extern "ws2_32" fn WSARecvDisconnect(
    s: usize, // SOCKET
    lpInboundDisconnectData: [*c]WSABUF // WSABUF* optional
) callconv(std.os.windows.WINAPI) i32;
proc WSARecvDisconnect(
    s: uint,  # SOCKET
    lpInboundDisconnectData: ptr WSABUF  # WSABUF* optional
): int32 {.importc: "WSARecvDisconnect", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
int WSARecvDisconnect(
    size_t s,   // SOCKET
    WSABUF* lpInboundDisconnectData   // WSABUF* optional
);
ccall((:WSARecvDisconnect, "WS2_32.dll"), stdcall, Int32,
      (Csize_t, Ptr{WSABUF}),
      s, lpInboundDisconnectData)
# s : SOCKET -> Csize_t
# lpInboundDisconnectData : WSABUF* optional -> Ptr{WSABUF}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t WSARecvDisconnect(
    uintptr_t s,
    void* lpInboundDisconnectData);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.WSARecvDisconnect(s, lpInboundDisconnectData)
-- s : SOCKET
-- lpInboundDisconnectData : WSABUF* optional
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const WSARecvDisconnect = lib.func('__stdcall', 'WSARecvDisconnect', 'int32_t', ['uintptr_t', 'void *']);
// WSARecvDisconnect(s, lpInboundDisconnectData)
// s : SOCKET -> 'uintptr_t'
// lpInboundDisconnectData : WSABUF* optional -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WS2_32.dll", {
  WSARecvDisconnect: { parameters: ["usize", "pointer"], result: "i32" },
});
// lib.symbols.WSARecvDisconnect(s, lpInboundDisconnectData)
// s : SOCKET -> "usize"
// lpInboundDisconnectData : WSABUF* optional -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t WSARecvDisconnect(
    size_t s,
    void* lpInboundDisconnectData);
C, "WS2_32.dll");
// $ffi->WSARecvDisconnect(s, lpInboundDisconnectData);
// s : SOCKET
// lpInboundDisconnectData : WSABUF* optional
// 構造体/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 WSARecvDisconnect(
        long s,   // SOCKET
        Pointer lpInboundDisconnectData   // WSABUF* optional
    );
}
@[Link("ws2_32")]
lib LibWS2_32
  fun WSARecvDisconnect = WSARecvDisconnect(
    s : LibC::SizeT,   # SOCKET
    lpInboundDisconnectData : WSABUF*   # WSABUF* optional
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

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

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

let wsarecvdisconnect =
  foreign "WSARecvDisconnect"
    (size_t @-> (ptr void) @-> returning int32_t)
(* s : SOCKET -> size_t *)
(* lpInboundDisconnectData : WSABUF* optional -> (ptr void) *)
(* 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 ("WSARecvDisconnect" wsarecv-disconnect :convention :stdcall) :int32
  (s :uint64)   ; SOCKET
  (lp-inbound-disconnect-data :pointer))   ; WSABUF* optional
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WSARecvDisconnect = Win32::API::More->new('WS2_32',
    'int WSARecvDisconnect(WPARAM s, LPVOID lpInboundDisconnectData)');
# my $ret = $WSARecvDisconnect->Call($s, $lpInboundDisconnectData);
# s : SOCKET -> WPARAM
# lpInboundDisconnectData : WSABUF* optional -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

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