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

WSACleanup

関数
Winsock DLLの利用を終了し資源を解放する。
DLLWS2_32.dll呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

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

INT WSACleanup(void);

パラメーターなし。戻り値: INT

公式ドキュメント

WSACleanup 関数 (winsock.h) は、WS2_32.dll の使用を終了します。

戻り値

操作が成功した場合、戻り値は 0 です。それ以外の場合は値 SOCKET_ERROR が返され、 WSAGetLastError を呼び出すことで特定のエラー番号を取得できます。

マルチスレッド環境では、 WSACleanup はすべてのスレッドの Windows Sockets 操作を終了します。

エラーコード 意味
WSANOTINITIALISED
この関数を使用する前に、 WSAStartup の呼び出しが成功している必要があります。
WSAENETDOWN
ネットワークサブシステムに障害が発生しました。
WSAEINPROGRESS
ブロッキング型の Windows Sockets 1.1 呼び出しが進行中であるか、サービスプロバイダーがまだコールバック関数を処理しています。

解説(Remarks)

アプリケーションまたは DLL は、Windows Sockets サービスを使用する前に WSAStartup の呼び出しを成功させる必要があります。Windows Sockets の使用を終えたら、アプリケーションまたは DLL は WSACleanup を呼び出して、Windows Sockets 実装から自身の登録を解除し、実装がアプリケーションまたは DLL のために割り当てたリソースを解放できるようにする必要があります。

WSACleanup が呼び出されると、このプロセス内の任意のスレッドが発行した保留中のブロッキング型または非同期の Windows Sockets 呼び出しは、通知メッセージの送信やイベントオブジェクトのシグナル通知を行うことなくキャンセルされます。このプロセス内の任意のスレッドが発行した保留中のオーバーラップ送受信操作 (たとえば、オーバーラップされた socket を使用した WSASendWSASendToWSARecvWSARecvFrom) も、イベントオブジェクトの設定や(指定されていた場合の)完了ルーチンの呼び出しを行うことなくキャンセルされます。この場合、保留中のオーバーラップ操作はエラーステータス WSA_OPERATION_ABORTED で失敗します。

WSACleanup が呼び出されたときに開いていた socket は、 closesocket が呼び出されたかのようにリセットされ、自動的に解放されます。 closesocket で閉じられたものの、まだ送信待ちのデータが残っている socket は、 WSACleanup が呼び出されると影響を受ける可能性があります。この場合、アプリケーションの終了時に WS2_32.DLL がメモリからアンロードされると、保留中のデータが失われる可能性があります。すべての保留中のデータが送信されることを保証するには、アプリケーションは shutdown を使用して接続を閉じ、クローズが完了するまで待ってから closesocketWSACleanup を呼び出す必要があります。キューに入れられた未投稿または投稿済みのメッセージなど、すべてのリソースと内部状態は、次のユーザーが利用できるように解放されなければなりません。

WSAStartup の成功した各呼び出しに対して、 WSACleanup の呼び出しが 1 回必要です。実際のクリーンアップを実行するのは、最後の WSACleanup 関数呼び出しのみです。それ以前の呼び出しは、単に WS2_32.DLL 内の内部参照カウントをデクリメントするだけです。

注意 WSACleanup は、Peer Name Resolution Protocol (PNRP) 名前空間プロバイダーなどの Windows Sockets 名前空間プロバイダーに登録された可能性のある名前 (たとえばピア名) の登録解除は行いません。
Windows Sockets 1.1 では、ブロッキングフック内から WSACleanup を呼び出そうとして戻りコードのチェックを怠ることが、よくあるプログラミングエラーでした。Winsock 1.1 アプリケーションがブロッキング呼び出しが未完了の状態で終了する必要がある場合、アプリケーションはまず WSACancelBlockingCall でブロッキング呼び出しをキャンセルし、制御がアプリケーションに戻ってから WSACleanup 呼び出しを発行する必要があります。Windows Sockets 2 ではこの問題は存在せず、WSACancelBlockingCall 関数は削除されています。

WSACleanup 関数は通常、プロトコル固有のヘルパー DLL のアンロードにつながります。そのため、 WSACleanup 関数をアプリケーション DLL の DllMain 関数から呼び出すべきではありません。これはデッドロックを引き起こす可能性があります。詳細については、DLL Main Function を参照してください。

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 WSACleanup(void);
[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern int WSACleanup();
<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WSACleanup() As Integer
End Function
Declare PtrSafe Function WSACleanup Lib "ws2_32" () As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

WSACleanup = ctypes.windll.ws2_32.WSACleanup
WSACleanup.restype = ctypes.c_int
WSACleanup.argtypes = []
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

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

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procWSACleanup = ws2_32.NewProc("WSACleanup")
)

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

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

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

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

let wsacleanup =
  foreign "WSACleanup"
    (void @-> returning 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 ("WSACleanup" wsacleanup :convention :stdcall) :int32)
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WSACleanup = Win32::API::More->new('WS2_32',
    'int WSACleanup()');
# my $ret = $WSACleanup->Call();
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目