Función WSAConnectByNameA (winsock2.h)

La función WSAConnectByName establece una conexión a un host y puerto especificados. Esta función se proporciona para permitir una conexión rápida a un punto de conexión de red dado un nombre de host y un puerto.

Esta función admite direcciones IPv4 e IPv6.

Sintaxis

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
);

Parámetros

[in] s

Descriptor que identifica un socket no conectado.

Nota En Windows 7, Windows Server 2008 R2 y versiones anteriores, la función WSAConnectByName requiere un socket independiente y sin conexión. Esto difiere de otras llamadas de Winsock para establecer una conexión (por ejemplo, WSAConnect).
 

[in] nodename

Cadena terminada en NULL que contiene el nombre del host o la dirección IP del host en la que se va a conectar para IPv4 o IPv6.

[in] servicename

Cadena terminada en NULL que contiene el nombre del servicio o el puerto de destino del host en el que se va a conectar para IPv4 o IPv6.

Un nombre de servicio es un alias de cadena para un número de puerto. Por ejemplo, "http" es un alias para el puerto 80 definido por el Grupo de tareas de ingeniería de Internet (IETF) como el puerto predeterminado que usan los servidores web para el protocolo HTTP. Los valores posibles para el parámetro servicename cuando no se especifica un número de puerto se muestran en el siguiente archivo:

%WINDIR%\system32\drivers\etc\services

[in, out] LocalAddressLength

En la entrada, un puntero al tamaño, en bytes, del búfer LocalAddress proporcionado por el autor de la llamada. En la salida, un puntero al tamaño, en bytes, del SOCKADDR para la dirección local almacenada en el búfer LocalAddress rellenado por el sistema tras completar correctamente la llamada.

[out] LocalAddress

Puntero a la estructura SOCKADDR que recibe la dirección local de la conexión. El tamaño del parámetro es exactamente el tamaño devuelto en LocalAddressLength. Esta es la misma información que devolvería la función getsockname . Este parámetro puede ser NULL, en cuyo caso, se omite el parámetro LocalAddressLength .

[in, out] RemoteAddressLength

En la entrada, un puntero al tamaño, en bytes, del búfer RemoteAddress proporcionado por el autor de la llamada. En la salida, un puntero al tamaño, en bytes, del SOCKADDR para la dirección remota almacenada en el búfer remoteAddress rellenado por el sistema tras completar correctamente la llamada.

[out] RemoteAddress

Puntero a la estructura SOCKADDR que recibe la dirección remota de la conexión. Esta es la misma información que devolvería la función getpeername . Este parámetro puede ser NULL, en cuyo caso se omite RemoteAddressLength .

[in] timeout

El tiempo, en milisegundos, para esperar una respuesta de la aplicación remota antes de anular la llamada.

Reserved

Reservado para la implementación futura. Este parámetro debe establecerse en NULL.

Valor devuelto

Si se establece una conexión, WSAConnectByName devuelve los parámetros TRUE y LocalAddress y RemoteAddress se rellenan si el autor de la llamada proporcionó estos búferes.

Si se produce un error en la llamada, se devuelve FALSE . A continuación, se puede llamar a WSAGetLastError para obtener información de error extendida.

Código devuelto Descripción
WSAEHOSTUNREACH
El host pasado como parámetro nodename no era accesible.
WSAEINVAL
Se pasó un parámetro no válido a la función. El parámetro nodename o servicename no debe ser NULL. El parámetro Reserved debe ser NULL.
WSAENOBUFS
No se pudo asignar memoria suficiente.
WSAENOTSOCK
Se pasó un socket no válido a la función. El parámetro s no debe ser INVALID_SOCKET ni NULL.
WSAETIMEDOUT
No se recibió una respuesta de la aplicación remota antes de que se superara el parámetro de tiempo de espera .

Comentarios

WSAConnectByName se proporciona para habilitar conexiones rápidas y transparentes a hosts remotos en puertos específicos. Es compatible con las versiones IPv6 e IPv4.

Para habilitar las comunicaciones IPv6 e IPv4, use el método siguiente:

  • Se debe llamar a la función setsockopt en un socket creado para la familia de direcciones AF_INET6 para deshabilitar la opción de socket IPV6_V6ONLY antes de llamar a WSAConnectByName. Esto se logra mediante una llamada a la función setsockopt en el socket con el parámetro level establecido en IPPROTO_IPV6 (vea IPPROTO_IPV6 Opciones de socket), el parámetro optname establecido en IPV6_V6ONLY y el valor del parámetro optvalue establecido en cero .

WSAConnectByName tiene limitaciones: solo funciona para sockets orientados a la conexión, como los de tipo SOCK_STREAM. La función no admite la E/S superpuesta o el comportamiento de no bloqueo. WSAConnectByName se bloqueará incluso si el socket está en modo de no bloqueo.

WSAConnectByName no admite datos proporcionados por el usuario durante el establecimiento de una conexión. Esta llamada tampoco admite estructuras FLOWSPEC. En los casos en los que se requieren estas características, se debe usar WSAConnect en su lugar.

En versiones anteriores a Windows 10, si una aplicación necesita enlazarse a una dirección o puerto local específica, no se puede usar WSAConnectByName, ya que el parámetro de socket para WSAConnectByName debe ser un socket independiente.

Esta restricción se quitó Windows 10.

Los parámetros RemoteAddress y LocalAddress apuntan a una estructura SOCKADDR , que es un tipo de datos genérico. Cuando se llama a WSAConnectByName , se espera que un tipo de dirección de socket específico del protocolo de red o la familia de direcciones que se use se pase realmente en estos parámetros. Por lo tanto, para las direcciones IPv4, un puntero a una estructura de sockaddr_in se convertirá en un puntero a SOCKADDR como los parámetros RemoteAddress y LocalAddress . En el caso de las direcciones IPv6, un puntero a una estructura de sockaddr_in6 se convertiría en un puntero a SOCKADDR como los parámetros RemoteAddress y LocalAddress .

Cuando la función WSAConnectByName devuelve TRUE, el socket s está en el estado predeterminado de un socket conectado. El socket s no habilita las propiedades o opciones establecidas previamente hasta que SO_UPDATE_CONNECT_CONTEXT se establece en el socket. Use la función setsockopt para establecer la opción SO_UPDATE_CONNECT_CONTEXT.

Por ejemplo:

//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 Al emitir una llamada de Winsock de bloqueo como WSAConnectByName con el parámetro de tiempo de espera establecido en NULL, Winsock puede necesitar esperar un evento de red antes de que se pueda completar la llamada. Winsock realiza una espera alertable en esta situación, que se puede interrumpir mediante una llamada de procedimiento asincrónica (APC) programada en el mismo subproceso. La emisión de otra llamada winsock de bloqueo dentro de un APC que interrumpió una llamada de Winsock de bloqueo en curso en el mismo subproceso provocará un comportamiento indefinido y los clientes winsock nunca deben intentarlo.
 
Windows Phone 8: la función WSAConnectByNameW es compatible con las aplicaciones de la Tienda Windows Phone en Windows Phone 8 y versiones posteriores.

Windows 8.1 y Windows Server 2012 R2: la función WSAConnectByNameW es compatible con las aplicaciones de la Tienda Windows en Windows 8.1, Windows Server 2012 R2 y versiones posteriores.

Ejemplos

Establezca una conexión mediante 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

El encabezado winsock2.h define WSAConnectByName como alias que selecciona automáticamente la versión ANSI o Unicode de esta función en función de la definición de la constante de preprocesador UNICODE. La combinación del uso del alias neutral de codificación con código que no es neutral de codificación puede dar lugar a errores de coincidencia que dan lugar a errores de compilación o tiempo de ejecución. Para obtener más información, vea Convenciones para prototipos de función.

Requisitos

Requisito Value
Cliente mínimo compatible Windows 8.1, Windows Vista [aplicaciones de escritorio | Aplicaciones para UWP]
Servidor mínimo compatible Windows Server 2008 [aplicaciones de escritorio | aplicaciones para UWP]
Plataforma de destino Windows
Encabezado winsock2.h
Library Ws2_32.lib
Archivo DLL Ws2_32.dll

Consulte también

Opciones de socket de IPPROTO_IPV6

SOCKADDR

WSAConnect

WSAConnectByList

WSAGetLastError

getaddrinfo

getpeername

getsockname

setsockopt