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

WSAConnectByNameA

関数
ホスト名とサービス名を指定して接続を確立する。
DLLWS2_32.dll文字セットANSI (-A)呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

// WS2_32.dll  (ANSI / -A)
#include <windows.h>

BOOL WSAConnectByNameA(
    SOCKET s,
    LPCSTR nodename,
    LPCSTR servicename,
    DWORD* LocalAddressLength,   // optional
    SOCKADDR* LocalAddress,   // optional
    DWORD* RemoteAddressLength,   // optional
    SOCKADDR* RemoteAddress,   // optional
    const TIMEVAL* timeout,   // optional
    OVERLAPPED* Reserved   // optional
);

パラメーター

名前方向説明
sSOCKETin

未接続のソケットを識別するディスクリプタです。

Windows 7、Windows Server 2008 R2 以前では、WSAConnectByName 関数はバインドされておらず、かつ未接続のソケットを必要とします。これは接続を確立する他の Winsock 呼び出し(例: WSAConnect)とは異なります。
nodenameLPCSTRinIPv4 または IPv6 で接続先となるホストの名前、またはホストの IP アドレスを含む NULL 終端文字列です。
servicenameLPCSTRin

IPv4 または IPv6 で接続先となるホストのサービス名、または宛先ポートを含む NULL 終端文字列です。

サービス名はポート番号に対する文字列のエイリアスです。たとえば「http」はポート 80 のエイリアスであり、これは Web サーバが HTTP プロトコルで使用する既定ポートとして Internet Engineering Task Force (IETF) によって定義されています。ポート番号が指定されていない場合に servicename パラメータに指定可能な値は、次のファイルに記載されています。

%WINDIR%\system32\drivers\etc\services

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呼び出しを中止するまでに、リモートアプリケーションからの応答を待機する時間(ミリ秒単位)です。
ReservedOVERLAPPED*optional将来の実装のために予約されています。このパラメータは NULL に設定する必要があります。

戻り値の型: BOOL

公式ドキュメント

指定されたホストおよびポートへの接続を確立します。(ANSI)

戻り値

接続が確立されると、WSAConnectByNameTRUE を返し、呼び出し側がバッファを提供していれば LocalAddress および RemoteAddress パラメータが設定されます。

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

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

解説(Remarks)

WSAConnectByName は、特定のポート上のリモートホストへの迅速かつ透過的な接続を可能にするために提供されています。IPv6 と IPv4 の両バージョンに対応しています。

IPv6 と IPv4 の両方の通信を有効にするには、次の方法を使用します。

WSAConnectByName には次の制限があります。 この関数は、SOCK_STREAM 型のような、コネクション指向のソケットでのみ動作します。 この関数はオーバーラップ I/O やノンブロッキング動作をサポートしません。WSAConnectByName は、ソケットがノンブロッキングモードであってもブロックします。

WSAConnectByName は、接続確立時にユーザが指定するデータをサポートしません。また、この呼び出しは FLOWSPEC 構造体もサポートしません。これらの機能が必要な場合は、代わりに WSAConnect を使用する必要があります。

Windows 10 より前のバージョンでは、アプリケーションが特定のローカルアドレスまたはポートにバインドする必要がある場合、WSAConnectByName は使用できません。WSAConnectByName の socket パラメータはバインドされていないソケットでなければならないためです。

この制限は Windows 10 で撤廃されました。

RemoteAddress および LocalAddress パラメータは、汎用のデータ型である SOCKADDR 構造体を指します。WSAConnectByName を呼び出す際には、実際には使用するネットワークプロトコルまたはアドレスファミリに固有のソケットアドレス型がこれらのパラメータに渡されることが想定されています。したがって IPv4 アドレスの場合、sockaddr_in 構造体へのポインタを SOCKADDR へのポインタにキャストして RemoteAddress および LocalAddress パラメータとして渡します。IPv6 アドレスの場合は、sockaddr_in6 構造体へのポインタを SOCKADDR へのポインタにキャストして RemoteAddress および LocalAddress パラメータとして渡します。

WSAConnectByName 関数が 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 );
WSAConnectByName のようなブロッキング Winsock 呼び出しを timeout パラメータを NULL に設定して発行する場合、Winsock は呼び出しを完了する前にネットワークイベントを待機する必要が生じることがあります。この状況では Winsock はアラート可能な待機を実行し、これは同じスレッドでスケジュールされた非同期プロシージャ呼び出し(APC)によって中断される可能性があります。同じスレッドで進行中のブロッキング Winsock 呼び出しを中断した APC の内部で別のブロッキング Winsock 呼び出しを発行すると、未定義の動作につながるため、Winsock クライアントは決してこれを試みてはなりません。
Windows Phone 8: WSAConnectByNameW 関数は、Windows Phone 8 以降の Windows Phone ストアアプリでサポートされています。

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

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

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <mswsock.h>   // Need for SO_UPDATE_CONNECT_CONTEXT
#include <stdio.h>

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

SOCKET
OpenAndConnect(LPWSTR NodeName, LPWSTR PortName) 
{
    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){
        wprintf(L"socket failed with error: %d\n", WSAGetLastError());
        return INVALID_SOCKET;
    }

    iResult = setsockopt(ConnSocket, IPPROTO_IPV6,
        IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
    if (iResult == SOCKET_ERROR){
        wprintf(L"setsockopt for IPV6_V6ONLY failed with error: %d\n",
            WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    bSuccess = WSAConnectByName(ConnSocket, NodeName, 
            PortName, &dwLocalAddr,
            (SOCKADDR*)&LocalAddr,
            &dwRemoteAddr,
            (SOCKADDR*)&RemoteAddr,
            NULL,
            NULL);
    if (!bSuccess){
        wprintf(L"WsaConnectByName failed with error: %d\n", WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       

    
    }

    iResult = setsockopt(ConnSocket, SOL_SOCKET,
        SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
    if (iResult == SOCKET_ERROR){
        wprintf(L"setsockopt for SO_UPDATE_CONNECT_CONTEXT failed with error: %d\n",
            WSAGetLastError());
        closesocket(ConnSocket);
        return INVALID_SOCKET;       
    }

    return ConnSocket;
}

int __cdecl wmain(int argc, wchar_t **argv)
{
   //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    SOCKET s = INVALID_SOCKET;

    // Validate the parameters
    if (argc != 3) {
        wprintf(L"usage: %ws <Nodename> <Portname>\n", argv[0]);
        wprintf(L"wsaconnectbyname establishes a connection to a specified host and port.\n");
        wprintf(L"%ws www.contoso.com 8080\n", argv[0]);
        return 1;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed: %d\n", iResult);
        return 1;
    }

    wprintf(L"WsaConnectByName with following parameters:\n");
    wprintf(L"\tNodename = %ws\n", argv[1]);
    wprintf(L"\tPortname (or port) = %ws\n\n", argv[2]);

    //--------------------------------
    // Call our function that uses the WsaConnectByName. 
    
    s = OpenAndConnect(argv[1], argv[2]);
    if ( s == INVALID_SOCKET ) {
        wprintf(L"WsaConnectByName failed with error: %d\n", WSAGetLastError());
        WSACleanup();
        return 1;
    }
    else
    {
        wprintf(L"WsaConnectByName succeeded\n");
        
        closesocket(s);
        WSACleanup();
        return 0;
    }
}
メモ

winsock2.h ヘッダは、UNICODE プリプロセッサ定数の定義に基づいて、この関数の ANSI 版または Unicode 版を自動的に選択するエイリアスとして WSAConnectByName を定義します。エンコーディング非依存のエイリアスの使用と、エンコーディング非依存でないコードを混在させると、不整合が生じてコンパイルエラーや実行時エラーにつながる可能性があります。詳細については、Conventions for Function Prototypes を参照してください。

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

各言語での呼び出し定義

// WS2_32.dll  (ANSI / -A)
#include <windows.h>

BOOL WSAConnectByNameA(
    SOCKET s,
    LPCSTR nodename,
    LPCSTR servicename,
    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", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
static extern bool WSAConnectByNameA(
    UIntPtr s,   // SOCKET
    [MarshalAs(UnmanagedType.LPStr)] string nodename,   // LPCSTR
    [MarshalAs(UnmanagedType.LPStr)] string servicename,   // LPCSTR
    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", CharSet:=CharSet.Ansi, SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WSAConnectByNameA(
    s As UIntPtr,   ' SOCKET
    <MarshalAs(UnmanagedType.LPStr)> nodename As String,   ' LPCSTR
    <MarshalAs(UnmanagedType.LPStr)> servicename As String,   ' LPCSTR
    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
' nodename : LPCSTR
' servicename : LPCSTR
' 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 WSAConnectByNameA Lib "ws2_32" ( _
    ByVal s As LongPtr, _
    ByVal nodename As String, _
    ByVal servicename As String, _
    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

WSAConnectByNameA = ctypes.windll.ws2_32.WSAConnectByNameA
WSAConnectByNameA.restype = wintypes.BOOL
WSAConnectByNameA.argtypes = [
    ctypes.c_size_t,  # s : SOCKET
    wintypes.LPCSTR,  # nodename : LPCSTR
    wintypes.LPCSTR,  # servicename : LPCSTR
    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')
WSAConnectByNameA = Fiddle::Function.new(
  lib['WSAConnectByNameA'],
  [
    Fiddle::TYPE_UINTPTR_T,  # s : SOCKET
    Fiddle::TYPE_VOIDP,  # nodename : LPCSTR
    Fiddle::TYPE_VOIDP,  # servicename : LPCSTR
    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 WSAConnectByNameA(
        s: usize,  // SOCKET
        nodename: *const u8,  // LPCSTR
        servicename: *const u8,  // LPCSTR
        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", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern bool WSAConnectByNameA(UIntPtr s, [MarshalAs(UnmanagedType.LPStr)] string nodename, [MarshalAs(UnmanagedType.LPStr)] string servicename, IntPtr LocalAddressLength, IntPtr LocalAddress, IntPtr RemoteAddressLength, IntPtr RemoteAddress, IntPtr timeout, IntPtr Reserved);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_WSAConnectByNameA' -Namespace Win32 -PassThru
# $api::WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
#uselib "WS2_32.dll"
#func global WSAConnectByNameA "WSAConnectByNameA" sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr
; WSAConnectByNameA s, nodename, servicename, varptr(LocalAddressLength), varptr(LocalAddress), varptr(RemoteAddressLength), varptr(RemoteAddress), varptr(timeout), varptr(Reserved)   ; 戻り値は stat
; s : SOCKET -> "sptr"
; nodename : LPCSTR -> "sptr"
; servicename : LPCSTR -> "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 WSAConnectByNameA "WSAConnectByNameA" sptr, str, str, var, var, var, var, var, var
; res = WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
; s : SOCKET -> "sptr"
; nodename : LPCSTR -> "str"
; servicename : LPCSTR -> "str"
; 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 WSAConnectByNameA(SOCKET s, LPCSTR nodename, LPCSTR servicename, DWORD* LocalAddressLength, SOCKADDR* LocalAddress, DWORD* RemoteAddressLength, SOCKADDR* RemoteAddress, TIMEVAL* timeout, OVERLAPPED* Reserved)
#uselib "WS2_32.dll"
#cfunc global WSAConnectByNameA "WSAConnectByNameA" intptr, str, str, var, var, var, var, var, var
; res = WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
; s : SOCKET -> "intptr"
; nodename : LPCSTR -> "str"
; servicename : LPCSTR -> "str"
; 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")
	procWSAConnectByNameA = ws2_32.NewProc("WSAConnectByNameA")
)

// s (SOCKET), nodename (LPCSTR), servicename (LPCSTR), 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 := procWSAConnectByNameA.Call(
	uintptr(s),
	uintptr(unsafe.Pointer(windows.BytePtrFromString(nodename))),
	uintptr(unsafe.Pointer(windows.BytePtrFromString(servicename))),
	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 WSAConnectByNameA(
  s: NativeUInt;   // SOCKET
  nodename: PAnsiChar;   // LPCSTR
  servicename: PAnsiChar;   // LPCSTR
  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 'WSAConnectByNameA';
result := DllCall("WS2_32\WSAConnectByNameA"
    , "UPtr", s   ; SOCKET
    , "AStr", nodename   ; LPCSTR
    , "AStr", servicename   ; LPCSTR
    , "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
●WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved) = DLL("WS2_32.dll", "bool WSAConnectByNameA(int, char*, char*, void*, void*, void*, void*, void*, void*)")
# 呼び出し: WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
# s : SOCKET -> "int"
# nodename : LPCSTR -> "char*"
# servicename : LPCSTR -> "char*"
# 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 WSAConnectByNameA(
    s: usize, // SOCKET
    nodename: [*c]const u8, // LPCSTR
    servicename: [*c]const u8, // LPCSTR
    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 WSAConnectByNameA(
    s: uint,  # SOCKET
    nodename: cstring,  # LPCSTR
    servicename: cstring,  # LPCSTR
    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: "WSAConnectByNameA", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
int WSAConnectByNameA(
    size_t s,   // SOCKET
    const(char)* nodename,   // LPCSTR
    const(char)* servicename,   // LPCSTR
    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((:WSAConnectByNameA, "WS2_32.dll"), stdcall, Int32,
      (Csize_t, Cstring, Cstring, Ptr{UInt32}, Ptr{SOCKADDR}, Ptr{UInt32}, Ptr{SOCKADDR}, Ptr{TIMEVAL}, Ptr{OVERLAPPED}),
      s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
# s : SOCKET -> Csize_t
# nodename : LPCSTR -> Cstring
# servicename : LPCSTR -> Cstring
# 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 WSAConnectByNameA(
    uintptr_t s,
    const char* nodename,
    const char* servicename,
    uint32_t* LocalAddressLength,
    void* LocalAddress,
    uint32_t* RemoteAddressLength,
    void* RemoteAddress,
    void* timeout,
    void* Reserved);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
-- s : SOCKET
-- nodename : LPCSTR
-- servicename : LPCSTR
-- 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 WSAConnectByNameA = lib.func('__stdcall', 'WSAConnectByNameA', 'int32_t', ['uintptr_t', 'str', 'str', 'uint32_t *', 'void *', 'uint32_t *', 'void *', 'void *', 'void *']);
// WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
// s : SOCKET -> 'uintptr_t'
// nodename : LPCSTR -> 'str'
// servicename : LPCSTR -> 'str'
// 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", {
  WSAConnectByNameA: { parameters: ["usize", "buffer", "buffer", "pointer", "pointer", "pointer", "pointer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
// s : SOCKET -> "usize"
// nodename : LPCSTR -> "buffer"
// servicename : LPCSTR -> "buffer"
// 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"。ANSI(-A) は new TextEncoder() で UTF-8/ANSI バイト列(末尾に \x00)を渡す。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t WSAConnectByNameA(
    size_t s,
    const char* nodename,
    const char* servicename,
    uint32_t* LocalAddressLength,
    void* LocalAddress,
    uint32_t* RemoteAddressLength,
    void* RemoteAddress,
    void* timeout,
    void* Reserved);
C, "WS2_32.dll");
// $ffi->WSAConnectByNameA(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved);
// s : SOCKET
// nodename : LPCSTR
// servicename : LPCSTR
// 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, W32APIOptions.ASCII_OPTIONS);
    boolean WSAConnectByNameA(
        long s,   // SOCKET
        String nodename,   // LPCSTR
        String servicename,   // LPCSTR
        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 WSAConnectByNameA = WSAConnectByNameA(
    s : LibC::SizeT,   # SOCKET
    nodename : UInt8*,   # LPCSTR
    servicename : UInt8*,   # LPCSTR
    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 WSAConnectByNameANative = Int32 Function(UintPtr, Pointer<Utf8>, Pointer<Utf8>, Pointer<Uint32>, Pointer<Void>, Pointer<Uint32>, Pointer<Void>, Pointer<Void>, Pointer<Void>);
typedef WSAConnectByNameADart = int Function(int, Pointer<Utf8>, Pointer<Utf8>, Pointer<Uint32>, Pointer<Void>, Pointer<Uint32>, Pointer<Void>, Pointer<Void>, Pointer<Void>);
final WSAConnectByNameA = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<WSAConnectByNameANative, WSAConnectByNameADart>('WSAConnectByNameA');
// s : SOCKET -> UintPtr
// nodename : LPCSTR -> Pointer<Utf8>
// servicename : LPCSTR -> Pointer<Utf8>
// 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 WSAConnectByNameA(
  s: NativeUInt;   // SOCKET
  nodename: PAnsiChar;   // LPCSTR
  servicename: PAnsiChar;   // LPCSTR
  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 'WSAConnectByNameA';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "WSAConnectByNameA"
  c_WSAConnectByNameA :: CUIntPtr -> CString -> CString -> Ptr Word32 -> Ptr () -> Ptr Word32 -> Ptr () -> Ptr () -> Ptr () -> IO CInt
-- s : SOCKET -> CUIntPtr
-- nodename : LPCSTR -> CString
-- servicename : LPCSTR -> CString
-- 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 wsaconnectbynamea =
  foreign "WSAConnectByNameA"
    (size_t @-> string @-> string @-> (ptr uint32_t) @-> (ptr void) @-> (ptr uint32_t) @-> (ptr void) @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* s : SOCKET -> size_t *)
(* nodename : LPCSTR -> string *)
(* servicename : LPCSTR -> string *)
(* 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 ("WSAConnectByNameA" wsaconnect-by-name-a :convention :stdcall) :int32
  (s :uint64)   ; SOCKET
  (nodename :string)   ; LPCSTR
  (servicename :string)   ; LPCSTR
  (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 $WSAConnectByNameA = Win32::API::More->new('WS2_32',
    'BOOL WSAConnectByNameA(WPARAM s, LPCSTR nodename, LPCSTR servicename, LPVOID LocalAddressLength, LPVOID LocalAddress, LPVOID RemoteAddressLength, LPVOID RemoteAddress, LPVOID timeout, LPVOID Reserved)');
# my $ret = $WSAConnectByNameA->Call($s, $nodename, $servicename, $LocalAddressLength, $LocalAddress, $RemoteAddressLength, $RemoteAddress, $timeout, $Reserved);
# s : SOCKET -> WPARAM
# nodename : LPCSTR -> LPCSTR
# servicename : LPCSTR -> LPCSTR
# 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 を使用。

関連項目

文字セット違い
公式の関連項目
使用する型