Condividi tramite


Funzione WSAConnectByList (winsock2.h)

La funzione WSAConnectByList stabilisce una connessione a una parte di una raccolta di possibili endpoint rappresentati da un set di indirizzi di destinazione (nomi host e porte). Questa funzione accetta tutti gli indirizzi di destinazione passati a esso e tutti gli indirizzi di origine del computer locale e prova a connettersi usando tutte le combinazioni di indirizzi possibili prima di rinunciare.

Questa funzione supporta sia indirizzi IPv4 che IPv6.

Sintassi

BOOL WSAConnectByList(
  [in]      SOCKET               s,
  [in]      PSOCKET_ADDRESS_LIST SocketAddress,
  [in, out] LPDWORD              LocalAddressLength,
  [out]     LPSOCKADDR           LocalAddress,
  [in, out] LPDWORD              RemoteAddressLength,
  [out]     LPSOCKADDR           RemoteAddress,
  [in]      const timeval        *timeout,
  [in]      LPWSAOVERLAPPED      Reserved
);

Parametri

[in] s

Descrittore che identifica un socket non connesso e non connesso. Si noti che a differenza di altre chiamate Winsock per stabilire una connessione (ad esempio WSAConnect), la funzione WSAConnectByList richiede un socket non in uscita.

[in] SocketAddress

Puntatore a una struttura SOCKET_ADDRESS_LIST che rappresenta l'indirizzo di destinazione e le coppie di porte possibili per connettersi a un peer. È responsabilità dell'applicazione compilare il numero di porta in ogni struttura SOCKET_ADDRESS nella SOCKET_ADDRESS_LIST.

[in, out] LocalAddressLength

In input, un puntatore alle dimensioni, in byte, del buffer LocalAddress fornito dal chiamante. Nell'output, un puntatore alle dimensioni, 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, in tal caso, il parametro LocalAddressLength viene ignorato.

[in, out] RemoteAddressLength

In input, un puntatore alle dimensioni, in byte, del buffer RemoteAddress fornito dal chiamante. Nell'output, un puntatore alle dimensioni, 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 restituite dalla funzione getpeername . Questo parametro può essere NULL, nel qual caso, remoteAddressLength viene ignorato.

[in] timeout

Tempo, in millisecondi, per attendere una risposta dall'applicazione remota prima di interrompere la chiamata. Questo parametro può essere NULL nel caso in cui WSAConnectByList venga completato dopo che la connessione è stata stabilita correttamente o dopo che è stata tentata una connessione e non è riuscita in tutte le possibili coppie di indirizzi remoti locali.

[in] Reserved

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

Valore restituito

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

Se la chiamata ha esito negativo, viene restituito FALSE . WSAGetLastError può quindi essere chiamato per ottenere informazioni di errore estese.

Codice restituito Descrizione
WSAEHOSTUNREACH
L'host passato come parametro nodename non è raggiungibile.
WSAEINVAL
Un parametro non valido è stato passato alla funzione. Il parametro Riservato deve essere NULL.
WSAENOBUFS
Impossibile allocare memoria sufficiente.
WSAENOTSOCK
Un socket non valido è stato passato alla funzione. 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

WSAConnectByList è simile alla funzione WSAConnectByName . Invece di prendere un singolo nome host e nome del servizio (porta), WSAConnectByList accetta un elenco di indirizzi (indirizzi host e porte) e si connette a uno degli indirizzi. La funzione WSAConnectByList è progettata per supportare scenari di collaborazione peer-to-peer in cui un'applicazione deve connettersi a qualsiasi nodo disponibile fuori da un elenco di potenziali nodi. WSAConnectByList è compatibile sia con le versioni IPv6 che IPv4.

Il set di destinazioni possibili, rappresentato da un elenco di indirizzi, viene fornito dal chiamante. WSAConnectByList tenta di connettersi a uno degli indirizzi di destinazione possibili. In particolare, la funzione accetta tutti gli indirizzi remoti passati dal chiamante, tutti gli indirizzi locali e quindi tenta una connessione usando le coppie di indirizzi con la maggiore probabilità di esito positivo. Di conseguenza, WSAConnectByList non garantisce solo che la connessione venga stabilita se una connessione è tutto possibile, ma riduce al minimo il tempo per stabilire la connessione.

Il chiamante può specificare i buffer e i buffer LocalAddress e RemoteAddress per determinare gli indirizzi locali e remoti per cui è stata stabilita correttamente la connessione.

Il parametro timeout consente al chiamante di limitare il tempo trascorso dalla funzione per stabilire una connessione. Internamente, WSAConnectByList esegue più operazioni (tentativi di connessione). Tra ogni operazione, il parametro timeout viene controllato per verificare se il timeout è stato superato e, in caso affermativo, la chiamata viene interrotta. Si noti che una singola operazione (connetti) non verrà interrotta una volta superato il timeout, pertanto la chiamata WSAConnectByList può richiedere più tempo rispetto al valore specificato nel parametro timeout.

WSAConnectByList 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. WSAConnectByList blocca anche se il socket è in modalità non di blocco. WSAConnectByList tenterà di connettersi (uno per uno) ai vari indirizzi forniti dal chiamante. Potenzialmente, ognuno di questi tentativi di connessione potrebbe non riuscire con un codice di errore diverso. Poiché è possibile restituire solo un singolo codice di errore, il valore restituito è il codice di errore dell'ultimo tentativo di connessione.

Per abilitare sia gli indirizzi IPv6 che IPv4 da passare nell'elenco di indirizzi singoli accettati dalla funzione, è necessario eseguire i passaggi seguenti prima di chiamare la funzione:

  • 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 WSAConnectByList. Questa operazione viene eseguita chiamando la funzione setockopt nel socket con il parametro di livello impostato su IPPROTO_IPV6 (vedere IPPROTO_IPV6 Opzioni socket), il parametro optname impostato su IPV6_V6ONLY e il valore del parametro optvalue impostato su zero .
  • Tutti gli indirizzi IPv4 devono essere rappresentati nel formato di indirizzi IPv4 mappato, che consente a un'applicazione IPv6 di comunicare con un nodo IPv4. Il formato di indirizzi IPv4 mappato a IPv6 consente l'indirizzo IPv4 di un nodo IPv4 da rappresentare come indirizzo IPv6. L'indirizzo IPv4 viene codificato nei 32 bit dell'indirizzo IPv6 e i bit a 96 bit con il prefisso fisso 0:0:0:0:0:0:FFFF. Il formato di indirizzi IPv4 mappato a IPv6 è specificato in RFC 4291. Per altre informazioni, vedere www.ietf.org/rfc/rfc4291.txt. La macro IN6ADDR_SETV4MAPPED in Mstcpip.h può essere usata per convertire un indirizzo IPv4 nel formato di indirizzi IPv4 mappato a IPv6 richiesto.

Le matrici di puntatori passati al parametro SocketAddressList puntano a una matrice di strutture SOCKET_ADDRESS , ovvero un tipo di dati generico. I parametri RemoteAddress e LocalAddress puntano anche alle strutture SOCKADDR. Quando viene chiamato WSAConnectByList , si prevede 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. Pertanto, per gli indirizzi IPv4, un puntatore a una struttura sockaddr_in verrà eseguito il cast in un puntatore a SOCKADDR quando viene passato come parametro. Per gli indirizzi IPv6, un puntatore a una struttura sockaddr_in6 verrà eseguito il cast in un puntatore a SOCKADDR quando viene passato come parametro. Il parametro SocketAddressList può contenere puntatori a una combinazione di indirizzi IPv4 e IPv6. Pertanto alcuni puntatori SOCKET_ADDRESS possono essere strutture sockaddr_in e altri possono essere sockaddr_in6 strutture. Se si prevede che gli indirizzi IPv6 possano essere usati, i parametri RemoteAddress e LocalAddress devono puntare a strutture sockaddr_in6 e essere distribuiti nelle strutture SOCKADDR . I parametri RemoteAddressLength e LocalAddressLength devono rappresentare la lunghezza di queste strutture più grandi.

Quando la funzione WSAConnectByList restituisce TRUE, il socket s si trova nello stato predefinito per un socket connesso. Il socket s non abilita le proprietà o le opzioni impostate in precedenza fino a quando non viene impostato SO_UPDATE_CONNECT_CONTEXT sul socket. Usare la funzione setockopt 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 emette una chiamata Winsock bloccante, ad esempio WSAConnectByList con il parametro timeout impostato su NULL, Winsock potrebbe dover attendere un evento di rete prima che la chiamata possa completare. Winsock esegue un'attesa avvisabile in questa situazione, che può essere interrotta da una chiamata di routine asincrona pianificata nello stesso thread. L'emissione di un'altra chiamata winsock bloccata 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 tentato dai client Winsock.
 
Windows Phone 8: questa funzione è supportata per le app Windows Phone Store in Windows Phone 8 e versioni successive.

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

Esempio

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

Requisiti

   
Client minimo supportato Windows 8.1, Windows Vista [app desktop | App UWP]
Server minimo supportato Windows Server 2003 [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

SOCKET_ADDRESS

SOCKET_ADDRESS_LIST

WSAConnect

WSAConnectByName

WSAGetLastError

getaddrinfo

getpeername

getsockname

Setsockopt