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

WSAConnectByList

関数
アドレス候補一覧から接続可能な相手へ接続する。
DLLWS2_32.dll呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

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

BOOL WSAConnectByList(
    SOCKET s,
    SOCKET_ADDRESS_LIST* SocketAddress,
    DWORD* LocalAddressLength,   // optional
    SOCKADDR* LocalAddress,   // optional
    DWORD* RemoteAddressLength,   // optional
    SOCKADDR* RemoteAddress,   // optional
    const TIMEVAL* timeout,   // optional
    OVERLAPPED* Reserved   // optional
);

パラメーター

名前方向説明
sSOCKETinバインドされておらず、接続もされていないソケットを識別するディスクリプタ。接続を確立する他の Winsock 呼び出し(たとえば WSAConnect)とは異なり、 WSAConnectByList 関数は バインドされていないソケットを必要とする点に注意してください。
SocketAddressSOCKET_ADDRESS_LIST*inピアへの接続に使用しうる宛先アドレスとポートの組を表す SOCKET_ADDRESS_LIST 構造体へのポインタ。SOCKET_ADDRESS_LIST 内の各 SOCKET_ADDRESS 構造体にポート番号を設定するのは、 アプリケーションの責任です。
LocalAddressLengthDWORD*inoutoptional入力時には、呼び出し側が用意した LocalAddress バッファのサイズ(バイト単位)へのポインタ。 出力時には、呼び出しが正常に完了したときにシステムが LocalAddress バッファに格納したローカルアドレスの SOCKADDR のサイズ(バイト単位)へのポインタ。
LocalAddressSOCKADDR*outoptional接続のローカルアドレスを受け取る SOCKADDR 構造体へのポインタ。 このパラメーターのサイズは LocalAddressLength で返されるサイズと正確に一致します。 これは getsockname 関数で返される情報と同じです。 このパラメーターには NULL を指定でき、その場合は LocalAddressLength パラメーターは 無視されます。
RemoteAddressLengthDWORD*inoutoptional入力時には、呼び出し側が用意した RemoteAddress バッファのサイズ(バイト単位)へのポインタ。 出力時には、呼び出しが正常に完了したときにシステムが RemoteAddress バッファに格納したリモートアドレスの SOCKADDR のサイズ(バイト単位)へのポインタ。
RemoteAddressSOCKADDR*outoptional接続のリモートアドレスを受け取る SOCKADDR 構造体へのポインタ。 これは getpeername 関数で返される情報と同じです。このパラメーターには NULL を指定でき、 その場合は RemoteAddressLength は無視されます。
timeoutTIMEVAL*inoptional呼び出しを中止するまでに、リモートアプリケーションからの応答を待つ時間(ミリ秒単位)。 このパラメーターには NULL を指定でき、その場合 WSAConnectByList は、 接続が正常に確立されるか、または接続を試行してすべてのローカル/リモートアドレスの組で失敗した後に 完了します。
ReservedOVERLAPPED*optional将来の実装のために予約されています。このパラメーターは NULL に設定する必要があります。

戻り値の型: BOOL

公式ドキュメント

宛先アドレス(ホスト名とポート)の集合で表される、複数の接続先候補のうちの 1 つへの接続を確立します。

戻り値

接続が確立された場合、 WSAConnectByListTRUE を返し、 これらのバッファが呼び出し側から指定されていれば LocalAddress および RemoteAddress パラメーターが 設定されます。

呼び出しが失敗した場合は FALSE が返されます。 その後 WSAGetLastError を呼び出して 詳細なエラー情報を取得できます。

戻り値コード 説明
WSAEHOSTUNREACH
nodename パラメーターとして渡されたホストに到達できませんでした。
WSAEINVAL
無効なパラメーターが関数に渡されました。Reserved パラメーターは NULL でなければなりません。
WSAENOBUFS
十分なメモリを割り当てられませんでした。
WSAENOTSOCK
無効なソケットが関数に渡されました。s パラメーターは INVALID_SOCKET または NULL であってはなりません。
WSAETIMEDOUT
timeout パラメーターで指定した時間を超えるまでに、リモートアプリケーションからの 応答を受信できませんでした。

解説(Remarks)

WSAConnectByListWSAConnectByName 関数に似ています。単一のホスト名とサービス名(ポート)を 受け取る代わりに、WSAConnectByList はアドレスのリスト(ホスト アドレスとポート)を受け取り、そのうちの 1 つのアドレスに接続します。 WSAConnectByList 関数は、 アプリケーションが候補ノードのリストの中から利用可能な任意のノードに接続する必要がある、 ピアツーピアの共同作業シナリオをサポートするように設計されています。WSAConnectByList は IPv6 版と IPv4 版の両方に対応しています。

接続先候補の集合は、アドレスのリストとして 呼び出し側から提供されます。WSAConnectByList は 単に複数の宛先アドレスのうち 1 つへの接続を試みる以上のことを行います。具体的には、この関数は 呼び出し側から渡されたすべてのリモートアドレスとすべてのローカルアドレスを受け取り、 成功する可能性が最も高いアドレスの組から順に接続を試みます。このように、 WSAConnectByList は接続が可能であれば必ず 接続が確立されることを保証するだけでなく、接続の確立にかかる時間も最小限に 抑えます。

呼び出し側は LocalAddress および RemoteAddress バッファとその長さを指定して、接続が正常に確立されたローカルおよびリモートアドレスを 特定できます。

timeout パラメーターにより、呼び出し側は接続の確立に関数が費やす時間を 制限できます。内部的には、 WSAConnectByList は複数の操作(接続試行)を実行します。各操作の合間に timeout パラメーターをチェックして timeout を超えていないかを確認し、 超えている場合は呼び出しを中止します。なお、個々の操作(connect)は timeout を超えても いったん開始されると中断されないため、WSAConnectByList の呼び出しが タイムアウトするまでに、timeout パラメーターで指定した値より長くかかる場合があります。

WSAConnectByList には制限があります。SOCK_STREAM 型などの コネクション指向のソケットでのみ動作します。この関数はオーバーラップ I/O や 非ブロッキング動作をサポートしません。WSAConnectByList は ソケットが非ブロッキングモードであってもブロックします。 WSAConnectByList は、呼び出し側から提供された各アドレスに 1 つずつ接続を試みます。これらの接続試行はそれぞれ異なるエラーコードで失敗する可能性があります。 返せるエラーコードは 1 つだけであるため、返される値は最後の接続試行のエラーコードに なります。

この関数が受け取る単一のアドレスリストに IPv6 と IPv4 の両方のアドレスを渡せるようにするには、 関数を呼び出す前に次の手順を実行する必要があります。

SocketAddressList パラメーターで渡されるポインタの配列は、汎用的なデータ型である SOCKET_ADDRESS 構造体の配列を指します。RemoteAddress および LocalAddress パラメーターも SOCKADDR 構造体を指します。WSAConnectByList を呼び出すときは、 実際には使用するネットワークプロトコルまたはアドレスファミリに固有のソケットアドレス型が これらのパラメーターに渡されることが想定されています。したがって IPv4 アドレスの場合は、 sockaddr_in 構造体へのポインタをパラメーターとして渡すときに SOCKADDR へのポインタに キャストします。IPv6 アドレスの場合は、sockaddr_in6 構造体へのポインタを パラメーターとして渡すときに SOCKADDR へのポインタにキャストします。 SocketAddressList パラメーターには、IPv4 アドレスと IPv6 アドレスが混在した ポインタを含めることができます。つまり、一部の SOCKET_ADDRESS ポインタは sockaddr_in 構造体を指し、他は sockaddr_in6 構造体を指すことが できます。IPv6 アドレスが使用される可能性がある場合は、RemoteAddress および LocalAddress パラメーターは sockaddr_in6 構造体を指し、SOCKADDR 構造体にキャストする必要があります。 RemoteAddressLength および LocalAddressLength パラメーターは、これらのより大きな 構造体の長さを表す必要があります。

WSAConnectByList 関数が TRUE を返すと、ソケット s は接続済みソケットの既定の状態になります。ソケット s では、SO_UPDATE_CONNECT_CONTEXT がソケットに設定されるまで、以前に設定したプロパティやオプションは有効になりません。SO_UPDATE_CONNECT_CONTEXT オプションを設定するには setsockopt 関数を使用します。

次に例を示します。

//Need to #include <mswsock.h> for SO_UPDATE_CONNECT_CONTEXT

int iResult = 0;

iResult = setsockopt( s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 );
注意 timeout パラメーターを NULL に設定して WSAConnectByList のようなブロッキング Winsock 呼び出しを発行する場合、Winsock は呼び出しが完了する前にネットワークイベントを待つ必要があることがあります。この状況では Winsock はアラート可能な待機を実行し、これは同じスレッドでスケジュールされた非同期プロシージャ呼び出し(APC)によって中断される可能性があります。同じスレッドで進行中のブロッキング Winsock 呼び出しを中断した APC の内部から別のブロッキング Winsock 呼び出しを発行すると、未定義の動作につながるため、Winsock クライアントは決して行ってはなりません。
Windows Phone 8: この関数は、Windows Phone 8 以降の Windows Phone Store アプリでサポートされます。

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

WSAConnectByList を使用して接続を確立します。

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")


SOCKET
OpenAndConnect(SOCKET_ADDRESS_LIST *AddressList) 
{
    SOCKET ConnSocket = INVALID_SOCKET;

    int ipv6only = 0;
    int iResult;
    BOOL bSuccess;

    SOCKADDR_STORAGE LocalAddr = {0};
    SOCKADDR_STORAGE RemoteAddr = {0};

    DWORD dwLocalAddr = sizeof(LocalAddr);
    DWORD dwRemoteAddr = sizeof(RemoteAddr);

    ConnSocket = socket(AF_INET6, SOCK_STREAM, 0);
    if (ConnSocket == INVALID_SOCKET){
        return INVALID_SOCKET;
    }

    iResult = setsockopt(ConnSocket, IPPROTO_IPV6,
        IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
    if (iResult == SOCKET_ERROR){
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    // AddressList may contain IPv6 and/or IPv4Mapped addresses
    bSuccess = WSAConnectByList(ConnSocket,
            AddressList,
            &dwLocalAddr,
            (SOCKADDR*)&LocalAddr,
            &dwRemoteAddr,
            (SOCKADDR*)&RemoteAddr,
            NULL,
            NULL);
    if (bSuccess){
        return ConnSocket;
    } else {
        return INVALID_SOCKET;
    }
}
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

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

BOOL WSAConnectByList(
    SOCKET s,
    SOCKET_ADDRESS_LIST* SocketAddress,
    DWORD* LocalAddressLength,   // optional
    SOCKADDR* LocalAddress,   // optional
    DWORD* RemoteAddressLength,   // optional
    SOCKADDR* RemoteAddress,   // optional
    const TIMEVAL* timeout,   // optional
    OVERLAPPED* Reserved   // optional
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool WSAConnectByList(
    UIntPtr s,   // SOCKET
    IntPtr SocketAddress,   // SOCKET_ADDRESS_LIST*
    IntPtr LocalAddressLength,   // DWORD* optional, in/out
    IntPtr LocalAddress,   // SOCKADDR* optional, out
    IntPtr RemoteAddressLength,   // DWORD* optional, in/out
    IntPtr RemoteAddress,   // SOCKADDR* optional, out
    IntPtr timeout,   // TIMEVAL* optional
    IntPtr Reserved   // OVERLAPPED* optional
);
<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WSAConnectByList(
    s As UIntPtr,   ' SOCKET
    SocketAddress As IntPtr,   ' SOCKET_ADDRESS_LIST*
    LocalAddressLength As IntPtr,   ' DWORD* optional, in/out
    LocalAddress As IntPtr,   ' SOCKADDR* optional, out
    RemoteAddressLength As IntPtr,   ' DWORD* optional, in/out
    RemoteAddress As IntPtr,   ' SOCKADDR* optional, out
    timeout As IntPtr,   ' TIMEVAL* optional
    Reserved As IntPtr   ' OVERLAPPED* optional
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
' s : SOCKET
' SocketAddress : SOCKET_ADDRESS_LIST*
' LocalAddressLength : DWORD* optional, in/out
' LocalAddress : SOCKADDR* optional, out
' RemoteAddressLength : DWORD* optional, in/out
' RemoteAddress : SOCKADDR* optional, out
' timeout : TIMEVAL* optional
' Reserved : OVERLAPPED* optional
Declare PtrSafe Function WSAConnectByList Lib "ws2_32" ( _
    ByVal s As LongPtr, _
    ByVal SocketAddress As LongPtr, _
    ByVal LocalAddressLength As LongPtr, _
    ByVal LocalAddress As LongPtr, _
    ByVal RemoteAddressLength As LongPtr, _
    ByVal RemoteAddress As LongPtr, _
    ByVal timeout As LongPtr, _
    ByVal Reserved As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

WSAConnectByList = ctypes.windll.ws2_32.WSAConnectByList
WSAConnectByList.restype = wintypes.BOOL
WSAConnectByList.argtypes = [
    ctypes.c_size_t,  # s : SOCKET
    ctypes.c_void_p,  # SocketAddress : SOCKET_ADDRESS_LIST*
    ctypes.POINTER(wintypes.DWORD),  # LocalAddressLength : DWORD* optional, in/out
    ctypes.c_void_p,  # LocalAddress : SOCKADDR* optional, out
    ctypes.POINTER(wintypes.DWORD),  # RemoteAddressLength : DWORD* optional, in/out
    ctypes.c_void_p,  # RemoteAddress : SOCKADDR* optional, out
    ctypes.c_void_p,  # timeout : TIMEVAL* optional
    ctypes.c_void_p,  # Reserved : OVERLAPPED* optional
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

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

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procWSAConnectByList = ws2_32.NewProc("WSAConnectByList")
)

// s (SOCKET), SocketAddress (SOCKET_ADDRESS_LIST*), LocalAddressLength (DWORD* optional, in/out), LocalAddress (SOCKADDR* optional, out), RemoteAddressLength (DWORD* optional, in/out), RemoteAddress (SOCKADDR* optional, out), timeout (TIMEVAL* optional), Reserved (OVERLAPPED* optional)
r1, _, err := procWSAConnectByList.Call(
	uintptr(s),
	uintptr(SocketAddress),
	uintptr(LocalAddressLength),
	uintptr(LocalAddress),
	uintptr(RemoteAddressLength),
	uintptr(RemoteAddress),
	uintptr(timeout),
	uintptr(Reserved),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // BOOL
function WSAConnectByList(
  s: NativeUInt;   // SOCKET
  SocketAddress: Pointer;   // SOCKET_ADDRESS_LIST*
  LocalAddressLength: Pointer;   // DWORD* optional, in/out
  LocalAddress: Pointer;   // SOCKADDR* optional, out
  RemoteAddressLength: Pointer;   // DWORD* optional, in/out
  RemoteAddress: Pointer;   // SOCKADDR* optional, out
  timeout: Pointer;   // TIMEVAL* optional
  Reserved: Pointer   // OVERLAPPED* optional
): BOOL; stdcall;
  external 'WS2_32.dll' name 'WSAConnectByList';
result := DllCall("WS2_32\WSAConnectByList"
    , "UPtr", s   ; SOCKET
    , "Ptr", SocketAddress   ; SOCKET_ADDRESS_LIST*
    , "Ptr", LocalAddressLength   ; DWORD* optional, in/out
    , "Ptr", LocalAddress   ; SOCKADDR* optional, out
    , "Ptr", RemoteAddressLength   ; DWORD* optional, in/out
    , "Ptr", RemoteAddress   ; SOCKADDR* optional, out
    , "Ptr", timeout   ; TIMEVAL* optional
    , "Ptr", Reserved   ; OVERLAPPED* optional
    , "Int")   ; return: BOOL
●WSAConnectByList(s, SocketAddress, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved) = DLL("WS2_32.dll", "bool WSAConnectByList(int, void*, void*, void*, void*, void*, void*, void*)")
# 呼び出し: WSAConnectByList(s, SocketAddress, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
# s : SOCKET -> "int"
# SocketAddress : SOCKET_ADDRESS_LIST* -> "void*"
# LocalAddressLength : DWORD* optional, in/out -> "void*"
# LocalAddress : SOCKADDR* optional, out -> "void*"
# RemoteAddressLength : DWORD* optional, in/out -> "void*"
# RemoteAddress : SOCKADDR* optional, out -> "void*"
# timeout : TIMEVAL* optional -> "void*"
# Reserved : OVERLAPPED* optional -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

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

typedef WSAConnectByListNative = Int32 Function(UintPtr, Pointer<Void>, Pointer<Uint32>, Pointer<Void>, Pointer<Uint32>, Pointer<Void>, Pointer<Void>, Pointer<Void>);
typedef WSAConnectByListDart = int Function(int, Pointer<Void>, Pointer<Uint32>, Pointer<Void>, Pointer<Uint32>, Pointer<Void>, Pointer<Void>, Pointer<Void>);
final WSAConnectByList = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<WSAConnectByListNative, WSAConnectByListDart>('WSAConnectByList');
// s : SOCKET -> UintPtr
// SocketAddress : SOCKET_ADDRESS_LIST* -> Pointer<Void>
// LocalAddressLength : DWORD* optional, in/out -> Pointer<Uint32>
// LocalAddress : SOCKADDR* optional, out -> Pointer<Void>
// RemoteAddressLength : DWORD* optional, in/out -> Pointer<Uint32>
// RemoteAddress : SOCKADDR* optional, out -> Pointer<Void>
// timeout : TIMEVAL* optional -> Pointer<Void>
// Reserved : OVERLAPPED* optional -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function WSAConnectByList(
  s: NativeUInt;   // SOCKET
  SocketAddress: Pointer;   // SOCKET_ADDRESS_LIST*
  LocalAddressLength: Pointer;   // DWORD* optional, in/out
  LocalAddress: Pointer;   // SOCKADDR* optional, out
  RemoteAddressLength: Pointer;   // DWORD* optional, in/out
  RemoteAddress: Pointer;   // SOCKADDR* optional, out
  timeout: Pointer;   // TIMEVAL* optional
  Reserved: Pointer   // OVERLAPPED* optional
): BOOL; stdcall;
  external 'WS2_32.dll' name 'WSAConnectByList';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "WSAConnectByList"
  c_WSAConnectByList :: CUIntPtr -> Ptr () -> Ptr Word32 -> Ptr () -> Ptr Word32 -> Ptr () -> Ptr () -> Ptr () -> IO CInt
-- s : SOCKET -> CUIntPtr
-- SocketAddress : SOCKET_ADDRESS_LIST* -> Ptr ()
-- LocalAddressLength : DWORD* optional, in/out -> Ptr Word32
-- LocalAddress : SOCKADDR* optional, out -> Ptr ()
-- RemoteAddressLength : DWORD* optional, in/out -> Ptr Word32
-- RemoteAddress : SOCKADDR* optional, out -> Ptr ()
-- timeout : TIMEVAL* optional -> Ptr ()
-- Reserved : OVERLAPPED* optional -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let wsaconnectbylist =
  foreign "WSAConnectByList"
    (size_t @-> (ptr void) @-> (ptr uint32_t) @-> (ptr void) @-> (ptr uint32_t) @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* s : SOCKET -> size_t *)
(* SocketAddress : SOCKET_ADDRESS_LIST* -> (ptr void) *)
(* LocalAddressLength : DWORD* optional, in/out -> (ptr uint32_t) *)
(* LocalAddress : SOCKADDR* optional, out -> (ptr void) *)
(* RemoteAddressLength : DWORD* optional, in/out -> (ptr uint32_t) *)
(* RemoteAddress : SOCKADDR* optional, out -> (ptr void) *)
(* timeout : TIMEVAL* optional -> (ptr void) *)
(* Reserved : OVERLAPPED* 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 ("WSAConnectByList" wsaconnect-by-list :convention :stdcall) :int32
  (s :uint64)   ; SOCKET
  (socket-address :pointer)   ; SOCKET_ADDRESS_LIST*
  (local-address-length :pointer)   ; DWORD* optional, in/out
  (local-address :pointer)   ; SOCKADDR* optional, out
  (remote-address-length :pointer)   ; DWORD* optional, in/out
  (remote-address :pointer)   ; SOCKADDR* optional, out
  (timeout :pointer)   ; TIMEVAL* optional
  (reserved :pointer))   ; OVERLAPPED* optional
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $WSAConnectByList = Win32::API::More->new('WS2_32',
    'BOOL WSAConnectByList(WPARAM s, LPVOID SocketAddress, LPVOID LocalAddressLength, LPVOID LocalAddress, LPVOID RemoteAddressLength, LPVOID RemoteAddress, LPVOID timeout, LPVOID Reserved)');
# my $ret = $WSAConnectByList->Call($s, $SocketAddress, $LocalAddressLength, $LocalAddress, $RemoteAddressLength, $RemoteAddress, $timeout, $Reserved);
# s : SOCKET -> WPARAM
# SocketAddress : SOCKET_ADDRESS_LIST* -> LPVOID
# LocalAddressLength : DWORD* optional, in/out -> LPVOID
# LocalAddress : SOCKADDR* optional, out -> LPVOID
# RemoteAddressLength : DWORD* optional, in/out -> LPVOID
# RemoteAddress : SOCKADDR* optional, out -> LPVOID
# timeout : TIMEVAL* optional -> LPVOID
# Reserved : OVERLAPPED* optional -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

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