Condividi tramite


Funzione WSAConnectByNameA (winsock2.h)

La funzione WSAConnectByName stabilisce una connessione a un host e a una porta specificati. Questa funzione viene fornita per consentire una connessione rapida a un endpoint di rete in base a un nome host e a una porta.

Questa funzione supporta sia indirizzi IPv4 che IPv6.

Sintassi

BOOL WSAConnectByNameA(
  [in]      SOCKET          s,
  [in]      LPCSTR          nodename,
  [in]      LPCSTR          servicename,
  [in, out] LPDWORD         LocalAddressLength,
  [out]     LPSOCKADDR      LocalAddress,
  [in, out] LPDWORD         RemoteAddressLength,
  [out]     LPSOCKADDR      RemoteAddress,
  [in]      const timeval   *timeout,
            LPWSAOVERLAPPED Reserved
);

Parametri

[in] s

Descrittore che identifica un socket non connesso.

Nota In Windows 7, Windows Server 2008 R2 e versioni precedenti, la funzione WSAConnectByName richiede un socket non associato e non connesso. Ciò è diverso da altre chiamate Winsock per stabilire una connessione, ad esempio WSAConnect.
 

[in] nodename

Stringa con terminazione NULL contenente il nome dell'host o l'indirizzo IP dell'host in cui connettersi per IPv4 o IPv6.

[in] servicename

Stringa con terminazione NULL contenente il nome del servizio o la porta di destinazione dell'host in cui connettersi per IPv4 o IPv6.

Un nome del servizio è un alias stringa per un numero di porta. Ad esempio, "http" è un alias per la porta 80 definita da Internet Engineering Task Force (IETF) come porta predefinita usata dai server Web per il protocollo HTTP. I valori possibili per il parametro servicename quando non viene specificato un numero di porta sono elencati nel file seguente:

%WINDIR%\system32\drivers\etc\services

[in, out] LocalAddressLength

In input, un puntatore alla dimensione, in byte, del buffer LocalAddress fornito dal chiamante. Nell'output, un puntatore alla dimensione, in byte, di SOCKADDR per l'indirizzo locale archiviato nel buffer LocalAddress compilato dal sistema al completamento della chiamata.

[out] LocalAddress

Puntatore alla struttura SOCKADDR che riceve l'indirizzo locale della connessione. Le dimensioni del parametro sono esattamente le dimensioni restituite in LocalAddressLength. Si tratta delle stesse informazioni restituite dalla funzione getsockname . Questo parametro può essere NULL, nel qual caso il parametro LocalAddressLength viene ignorato.

[in, out] RemoteAddressLength

In input, un puntatore alla dimensione, in byte, del buffer RemoteAddress fornito dal chiamante. Nell'output, un puntatore alla dimensione, in byte, di SOCKADDR per l'indirizzo remoto archiviato nel buffer RemoteAddress riempito dal sistema al completamento della chiamata.

[out] RemoteAddress

Puntatore alla struttura SOCKADDR che riceve l'indirizzo remoto della connessione. Si tratta delle stesse informazioni che verrebbero restituite dalla funzione getpeername . Questo parametro può essere NULL. In tal caso, RemoteAddressLength viene ignorato.

[in] timeout

Tempo, in millisecondi, di attesa di una risposta dall'applicazione remota prima di interrompere la chiamata.

Reserved

Riservato per l'implementazione futura. Questo parametro deve essere impostato su NULL.

Valore restituito

Se viene stabilita una connessione, WSAConnectByName restituisce TRUE e i parametri LocalAddress e RemoteAddress vengono compilati se questi buffer sono stati forniti dal chiamante.

Se la chiamata non riesce, viene restituito FALSE . WSAGetLastError può quindi essere chiamato per ottenere informazioni estese sull'errore.

Codice restituito Descrizione
WSAEHOSTUNREACH
L'host passato come parametro nodename non è raggiungibile.
WSAEINVAL
Alla funzione è stato passato un parametro non valido. Il parametro nodename o servicename non deve essere NULL. Il parametro Reserved deve essere NULL.
WSAENOBUFS
Impossibile allocare memoria sufficiente.
WSAENOTSOCK
Alla funzione è stato passato un socket non valido. Il parametro s non deve essere INVALID_SOCKET o NULL.
WSAETIMEDOUT
Una risposta dall'applicazione remota non è stata ricevuta prima del superamento del parametro di timeout .

Commenti

WSAConnectByName viene fornito per abilitare connessioni rapide e trasparenti agli host remoti su porte specifiche. È compatibile con entrambe le versioni IPv6 e IPv4.

Per abilitare le comunicazioni IPv6 e IPv4, usare il metodo seguente:

  • La funzione setsockopt deve essere chiamata su un socket creato per la famiglia di indirizzi AF_INET6 per disabilitare l'opzione socket IPV6_V6ONLY prima di chiamare WSAConnectByName. A tale scopo, chiamare la funzione setsockopt sul socket con il parametro level impostato su IPPROTO_IPV6 (vedere IPPROTO_IPV6 Socket Options), il parametro optname impostato su IPV6_V6ONLY e il valore del parametro optvalue impostato su zero .

WSAConnectByName presenta limitazioni: funziona solo per i socket orientati alla connessione, ad esempio quelli di tipo SOCK_STREAM. La funzione non supporta il comportamento di I/O sovrapposto o non bloccante. WSAConnectByName bloccherà anche se il socket è in modalità non bloccanti.

WSAConnectByName non supporta i dati forniti dall'utente durante la creazione di una connessione. Questa chiamata non supporta le strutture FLOWSPEC. Nei casi in cui queste funzionalità sono necessarie, è necessario usare invece WSAConnect .

Nelle versioni precedenti Windows 10, se un'applicazione deve essere associata a un indirizzo locale o a una porta specifica, non è possibile usare WSAConnectByName perché il parametro socket a WSAConnectByName deve essere un socket non associato.

Questa restrizione è stata rimossa Windows 10.

I parametri RemoteAddress e LocalAddress puntano a una struttura SOCKADDR , ovvero un tipo di dati generico. Quando viene chiamato WSAConnectByName , è previsto che un tipo di indirizzo socket specifico per il protocollo di rete o la famiglia di indirizzi in uso venga effettivamente passato in questi parametri. Per gli indirizzi IPv4, quindi, un puntatore a una struttura sockaddr_in verrebbe eseguito il cast a un puntatore a SOCKADDR come parametri RemoteAddress e LocalAddress . Per gli indirizzi IPv6, viene eseguito il cast di un puntatore a una struttura sockaddr_in6 a SOCKADDR come parametri RemoteAddress e LocalAddress .

Quando la funzione WSAConnectByName restituisce TRUE, il socket s è nello stato predefinito per un socket connesso. Il socket s non abilita le proprietà o le opzioni impostate in precedenza finché SO_UPDATE_CONNECT_CONTEXT non viene impostato sul socket. Usare la funzione setsockopt per impostare l'opzione SO_UPDATE_CONNECT_CONTEXT.

Ad esempio:

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

int iResult = 0;

iResult = setsockopt( s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0 );

Nota Quando si esegue una chiamata Winsock bloccante, ad esempio WSAConnectByName con il parametro di timeout impostato su NULL, Winsock potrebbe dover attendere un evento di rete prima che la chiamata possa essere completata. Winsock esegue un'attesa avvisabile in questa situazione, che può essere interrotta da una chiamata di procedura asincrona pianificata nello stesso thread. L'esecuzione di un'altra chiamata Winsock bloccante all'interno di un APC che ha interrotto una chiamata winsock in corso sullo stesso thread causerà un comportamento non definito e non deve mai essere tentata dai client Winsock.
 
Windows Phone 8: la funzione WSAConnectByNameW è supportata per Windows Phone app dello Store in Windows Phone 8 e versioni successive.

Windows 8.1 e Windows Server 2012 R2: la funzione WSAConnectByNameW è supportata per le app di Windows Store in Windows 8.1, Windows Server 2012 R2 e versioni successive.

Esempio

Stabilire una connessione usando 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;
    }
}

Nota

L'intestazione winsock2.h definisce WSAConnectByName come alias che seleziona automaticamente la versione ANSI o Unicode di questa funzione in base alla definizione della costante del preprocessore UNICODE. La combinazione dell'utilizzo dell'alias indipendente dalla codifica con il codice che non è indipendente dalla codifica può causare mancate corrispondenze che generano errori di compilazione o di runtime. Per altre informazioni, vedere Convenzioni per i prototipi di funzioni.

Requisiti

Requisito Valore
Client minimo supportato Windows 8.1, Windows Vista [app desktop | App UWP]
Server minimo supportato Windows Server 2008 [app desktop | App UWP]
Piattaforma di destinazione Windows
Intestazione winsock2.h
Libreria Ws2_32.lib
DLL Ws2_32.dll

Vedi anche

Opzioni socket IPPROTO_IPV6

SOCKADDR

WSAConnect

WSAConnectByList

WSAGetLastError

getaddrinfo

getpeername

getsockname

Setsockopt