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 gli 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 di WSAConnectByName richiede un socket non associato e non connesso. Ciò differisce da altre chiamate Winsock per stabilire una connessione, ad esempio WSAConnect).
 

[in] nodename

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

[in] servicename

Valore NULLstringa con terminazione 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 nomeservizio quando non è specificato un numero di porta sono elencati nel file seguente:

%WINDIR%\system32\drivers\etc\services

[in, out] LocalAddressLength

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

[out] LocalAddress

Puntatore alla struttura SOCKADDR che riceve l'indirizzo locale della connessione. La dimensione del parametro è esattamente la dimensione restituita 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 caso di input, un puntatore alle dimensioni, in byte, del RemoteAddress buffer fornito dal chiamante. Nell'output, un puntatore alle dimensioni, in byte, del SOCKADDR per l'indirizzo remoto archiviato in RemoteAddress buffer 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 restituite dalla funzione getpeername. Questo parametro può essere NULL, nel qual caso, il 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 LocalAddress e i parametri RemoteAddress vengono compilati se questi buffer sono stati forniti dal chiamante.

Se la chiamata non riesce, viene restituito false. è possibile chiamare WSAGetLastError 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 nomeservizio non deve essere NULL. Il parametro riservato deve essere NULL.
WSAENOBUFS
Impossibile allocare memoria sufficiente.
WSAENOTSOCK
Alla funzione è stato passato un socket non valido. Il parametro del non deve essere INVALID_SOCKET o NULL.
WSAETIMEDOUT
Non è stata ricevuta una risposta dall'applicazione remota prima che il timeout parametro sia stato superato.

Osservazioni

WSAConnectByName 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 setockopt 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. Questa operazione viene eseguita chiamando la funzione setockopt di sul socket con il parametro livello di impostato su IPPROTO_IPV6 (vedere IPPROTO_IPV6 Socket Options), il parametro optname impostato su IPV6_V6ONLYe 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 si blocca 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 neanche le strutture FLOWSPEC. Nei casi in cui queste funzionalità sono necessarie, è necessario usare WSAConnect.

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

Questa restrizione è stata rimossa da Windows 10.

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

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

Per 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 il completamento di un evento di rete prima del completamento della chiamata. 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 comporterà un comportamento non definito e non deve mai essere tentata dai client Winsock.
 
Windows Phone 8: La funzione di WSAConnectByNameW è supportata per le app di Windows Phone 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.

Esempi

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 non indipendente dalla codifica può causare mancate corrispondenze che generano errori di compilazione o di runtime. Per altre informazioni, vedere convenzioni di per i prototipi di funzioni.

Fabbisogno

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 Finestre
intestazione winsock2.h
libreria Ws2_32.lib
dll Ws2_32.dll

Vedere anche

IPPROTO_IPV6 opzioni socket

SOCKADDR

WSAConnect

WSAConnectByList

WSAGetLastError

getaddrinfo

getpeername

getsockname

setockopt