Compartir a través de


Función WSAAccept (winsock2.h)

La función WSAAccept acepta condicionalmente una conexión basada en el valor devuelto de una función de condición, proporciona especificaciones de flujo de servicio de calidad y permite la transferencia de datos de conexión.

Sintaxis

SOCKET WSAAPI WSAAccept(
  [in]      SOCKET          s,
  [out]     sockaddr        *addr,
  [in, out] LPINT           addrlen,
  [in]      LPCONDITIONPROC lpfnCondition,
  [in]      DWORD_PTR       dwCallbackData
);

Parámetros

[in] s

Descriptor que identifica un socket que está escuchando conexiones después de una llamada a la función de escucha de .

[out] addr

Puntero opcional a una estructura de sockaddr que recibe la dirección de la entidad de conexión, como se conoce en la capa de comunicaciones. El formato exacto del parámetro addr viene determinado por la familia de direcciones establecida cuando se creó el socket.

[in, out] addrlen

Puntero opcional a un entero que contiene la longitud del estructura sockaddr a la que apunta el parámetro addr, en bytes.

[in] lpfnCondition

Dirección de una función de condición opcional especificada por la aplicación que tomará una decisión de aceptación o rechazo basada en la información del autor de la llamada que se pasa como parámetros y, opcionalmente, cree o una un grupo de sockets asignando un valor adecuado al parámetro de resultado g de esta función. Si este parámetro es NULL, no se llama a ninguna función condition.

[in] dwCallbackData

Los datos de devolución de llamada pasados a la función de condición especificada por la aplicación como el valor del parámetro dwCallbackData pasado a la función de condición. Este parámetro solo es aplicable si el parámetro lpfnCondition no es NULL. Windows Sockets no interpreta este parámetro.

Valor devuelto

Si no se produce ningún error, WSAAccept devuelve un valor de tipo SOCKET que es un descriptor para el socket aceptado. De lo contrario, se devuelve un valor de INVALID_SOCKET y se puede recuperar un código de error específico llamando a WSAGetLastError.

El entero al que hace referencia addrlen inicialmente contiene la cantidad de espacio al que apunta addr. Al devolver, contendrá la longitud real en bytes de la dirección devuelta.

Código de error Significado
WSAEACCES
Se intentó acceder a un socket de forma prohibida por sus permisos de acceso. Este error se devuelve si la solicitud de conexión que se ofreció ha agotado el tiempo de espera o se ha retirado.
WSAECONNREFUSED
No se pudo establecer ninguna conexión porque la máquina de destino la rechazó activamente. Este error se devuelve si la solicitud de conexión se rechazó forzadamente como se indica en el valor devuelto de la función de condición (CF_REJECT).
WSAECONNRESET
El host remoto cerró forzadamente una conexión existente. Este error se devuelve de una conexión entrante indicada, pero posteriormente lo finalizó el mismo nivel remoto antes de aceptar la llamada.
WSAEFAULT
El sistema detectó una dirección de puntero no válida al intentar usar un argumento de puntero en una llamada. Este error se devuelve del parámetro addrlen es demasiado pequeño o el addr o lpfnCondition no forma parte del espacio de direcciones del usuario.
WSAEINTR
Una operación de bloqueo se interrumpió mediante una llamada a WSACancelBlockingCall. Este error se devuelve si se canceló una llamada de Bloqueo de Windows Sockets 1.1 a través de WSACancelBlockingCall.
WSAEINPROGRESS
Actualmente se está ejecutando una operación de bloqueo. Este error se devuelve si una llamada a Windows Sockets 1.1 está en curso.
WSAEINVAL
Se proporcionó un argumento no válido. Este error se devuelve si de escucha no se invocó antes de WSAAccept, el valor devuelto de la función condition no es válido o si el socket especificado está en un estado no válido.
WSAEMFILE
Demasiados sockets abiertos. Este error se devuelve si la cola no está vacía tras la entrada a WSAAccept y no hay descriptores de socket disponibles.
WSAENETDOWN
Una operación de socket encontró una red inactiva. Este error se devuelve si se ha producido un error en el subsistema de red.
WSAENOBUFS
No se pudo realizar una operación en un socket porque el sistema no tenía suficiente espacio en búfer o porque una cola estaba llena. Este error se devuelve si no hay ningún espacio de búfer disponible.
WSAENOTSOCK
Se intentó realizar una operación en algo que no es un socket. Este error se devuelve si el descriptor de socket pasado en el parámetro de no es un socket.
WSAEOPNOTSUPP
La familia de protocolos no se ha configurado en el sistema o no existe ninguna implementación para ella. Este error se devuelve si el socket al que se hace referencia no es un tipo que admite el servicio orientado a la conexión.
WSAEWOULDBLOCK
No se pudo completar inmediatamente una operación de socket sin bloqueo. Este error se devuelve si el socket está marcado como no desbloqueado y no hay conexiones que se acepten.
WSANOTINITIALISED
No se ha llamado a la aplicación WSAStartupo error WSAStartup. Este error se devuelve de una llamada correcta a la WSAStartup función dit no se produce antes de usar esta función.
WSATRY_AGAIN
Normalmente se trata de un error temporal durante la resolución del nombre de host y significa que el servidor local no recibió una respuesta de un servidor autoritativo. Este error se devuelve si la aceptación de la solicitud de conexión se aplaza como se indica en el valor devuelto de la función de condición (CF_DEFER).

Observaciones

La función WSAAccept extrae la primera conexión en la cola de conexiones pendientes en el socket sy la comprueba con la función condition, siempre que se especifique la función condition (es decir, no NULL). Si la función condition devuelve CF_ACCEPT, WSAAccept crea un nuevo socket. El socket recién creado tiene las mismas propiedades que el de socket , incluidos los eventos asincrónicos registrados con WSAAsyncSelect o con WSAEventSelect. Si la función condition devuelve CF_REJECT, WSAAccept rechaza la solicitud de conexión. La función condition se ejecuta en el mismo subproceso que esta función y debe devolver lo antes posible. Si no se puede tomar la decisión inmediatamente, la función de condición debe devolver CF_DEFER para indicar que no se ha tomado ninguna decisión y que el proveedor de servicios debe tomar ninguna acción sobre esta solicitud de conexión. Cuando la aplicación esté lista para tomar medidas en la solicitud de conexión, invocará WSAAccept de nuevo y devolverá CF_ACCEPT o CF_REJECT como valor devuelto de la función condition.

Un socket en modo predeterminado (bloqueo) se bloqueará hasta que una conexión esté presente cuando una aplicación llame a WSAAccept y no haya conexiones pendientes en la cola.

Se produce un error en un socket en modo de no bloqueo (bloqueo) con el error WSAEWOULDBLOCK cuando una aplicación llama a WSAAccept y no hay ninguna conexión pendiente en la cola. Después de WSAAccept se realiza correctamente y devuelve un nuevo identificador de socket, el socket aceptado no se puede usar para aceptar más conexiones. El socket original permanece abierto y escucha las nuevas solicitudes de conexión.

El parámetro addr es un parámetro de resultado que se rellena con la dirección de la entidad de conexión, como se conoce en la capa de comunicaciones. El formato exacto del parámetro addr viene determinado por la familia de direcciones en la que se está produciendo la comunicación. El addrlen es un parámetro value-result; debe contener inicialmente la cantidad de espacio a la que apunta addr. Al devolverlo, contendrá la longitud real (en bytes) de la dirección devuelta. Esta llamada se usa con tipos de socket orientados a la conexión, como SOCK_STREAM. Si y/o addrlen son iguales a null, no se devuelve información sobre la dirección remota del socket aceptado. De lo contrario, estos dos parámetros se rellenarán si la conexión se acepta correctamente.

Un prototipo de la función condition se define en el archivo de encabezado Winsock2.h como el LPCONDITIONPROC, como se indica a continuación.

int CALLBACK 
ConditionFunc( 
  IN     LPWSABUF    lpCallerId, 
  IN     LPWSABUF    lpCallerData, 
  IN OUT LPQOS       lpSQOS, 
  IN OUT LPQOS       lpGQOS,
  IN     LPWSABUF    lpCalleeId, 
  IN     LPWSABUF    lpCalleeData, 
  OUT    GROUP FAR * g, 	
  IN     DWORD_PTR   dwCallbackData
);

El ConditionFunc de es un marcador de posición para la función de devolución de llamada especificada por la aplicación. La función de condición real debe residir en un módulo DLL o de aplicación. Se exporta en el archivo de definición del módulo.

El parámetro lpCallerId apunta a una estructura WSABUF que contiene la dirección de la entidad de conexión, donde su parámetro len es la longitud del búfer en bytes y su parámetro buf es un puntero al búfer. El lpCallerData es un parámetro de valor que contiene los datos de usuario. La información de estos parámetros se envía junto con la solicitud de conexión. Si no hay ningún dato de identificación o autor de llamada disponible, los parámetros correspondientes serán NULL. Muchos protocolos de red no admiten datos del autor de llamada en tiempo de conexión. Se espera que la mayoría de los protocolos de red convencionales admitan la información del identificador de llamada en el momento de la solicitud de conexión. La parte buf del WSABUF apunta a por lpCallerId apunta a un sockaddr. La estructura sockaddr se interpreta según su familia de direcciones (normalmente mediante la conversión de la a algún tipo específico de la familia de direcciones).

El parámetro lpSQOS hace referencia a las estructuras de FLOWSPEC para el de socket especificado por el autor de la llamada, uno para cada dirección, seguido de cualquier parámetro adicional específico del proveedor. Los valores de especificación de flujo de envío o recepción se omitirán según corresponda para los sockets unidireccionales. Un valor NULL indica que no hay calidad de servicio proporcionada por el autor de la llamada y que no es posible ninguna negociación. Un puntero denoNULLlpSQOS indica que se va a producir una negociación de calidad de servicio o que el proveedor está preparado para aceptar la calidad de la solicitud de servicio sin negociación.

El parámetro lpGQOS está reservado y debe ser null. (reservado para uso futuro con grupos de sockets) hace referencia a la estructura FLOWSPEC para el grupo de sockets que el autor de la llamada va a crear, uno para cada dirección, seguido de cualquier parámetro adicional específico del proveedor. Un valor de NULL para lpGQOS indica que no hay calidad de servicio especificada por el autor de la llamada. Se puede devolver la información de calidad del servicio si se va a producir la negociación.

El lpCalleeId es un parámetro que contiene la dirección local de la entidad conectada. El buf parte del WSABUF al que apunta lpCalleeId apunta a una estructura de . La estructura sockaddr se interpreta según su familia de direcciones (normalmente mediante la conversión de la a algún tipo específico de la familia de direcciones, como la estructura sockaddr_in).

El lpCalleeData es un parámetro de resultado utilizado por la función condition para devolver los datos de usuario a la entidad de conexión. El lpCalleeData-> inicialmente contiene la longitud del búfer asignado por el proveedor de servicios y apuntado por lpCalleeData->buf. Un valor de cero significa que no se admite la transferencia de datos de usuario al autor de la llamada. La función condition debe copiar hasta lpCalleeData->len bytes de datos en lpCalleeData->bufy, a continuación, actualizar lpCalleeData->len para indicar el número real de bytes transferidos. Si no hay datos de usuario que se devuelvan al autor de la llamada, la función condition debe establecer lpCalleeData->len en cero. El formato de todos los datos de dirección y usuario es específico de la familia de direcciones a la que pertenece el socket.

El parámetro g se asigna dentro de la función condition para indicar cualquiera de las acciones siguientes:

  • Si g es un identificador de grupo de sockets existente, agregue s a este grupo, siempre que se cumplan todos los requisitos establecidos por este grupo.
  • Si g = SG_UNCONSTRAINED_GROUP, cree un grupo de sockets sin restricciones y tenga s como primer miembro.
  • Si g = SG_CONSTRAINED_GROUP, cree un grupo de sockets restringido y tenga s como primer miembro.
  • Si g = cero, no se realiza ninguna operación de grupo.
En el caso de los grupos sin restricciones, cualquier conjunto de sockets se puede agrupar siempre que sean compatibles con un único proveedor de servicios. Un grupo de sockets restringidos solo puede constar de sockets orientados a la conexión y requiere que las conexiones de todos los sockets agrupados sean a la misma dirección en el mismo host. Para los grupos de sockets recién creados, el nuevo identificador de grupo se puede recuperar mediante función getsockopt con nivel de parámetro establecido en SOL_SOCKET y el parámetro optname establecido en SO_GROUP_ID. Un grupo de sockets y su identificador de grupo de sockets asociado permanecen válidos hasta que se cierre el último socket que pertenece a este grupo de sockets. Los identificadores de grupo de sockets son únicos en todos los procesos de un proveedor de servicios determinado. Un grupo de sockets y su identificador asociado permanecen válidos hasta que se cierra el último socket que pertenece a este grupo de sockets. Los identificadores de grupo de sockets son únicos en todos los procesos de un proveedor de servicios determinado. Para obtener más información sobre los grupos de sockets, consulte los comentarios de las funciones de WSASocket .

El valor del parámetro dwCallbackData pasado a la función condition es el valor pasado como parámetro dwCallbackData en la llamada WSAAccept original. Este valor solo lo interpreta el cliente de Windows Socket versión 2. Esto permite que un cliente pase información de contexto del WSAAccept sitio de llamada a través de la función condition. Esto también proporciona la función condition con cualquier información adicional necesaria para determinar si se debe aceptar la conexión o no. Un uso típico es pasar un puntero (conversión adecuada) a una estructura de datos que contiene referencias a objetos definidos por la aplicación con los que está asociado este socket.

Nota Para proteger el uso de la función WSAAccept frente a ataques SYN, las aplicaciones deben realizar protocolos de enlace TCP completos (SYN-SYNACK-ACK) antes de notificar la solicitud de conexión. La protección contra ataques SYN de esta manera hace que la opción de socket de SO_CONDITIONAL_ACCEPT sea inoperativa; Se sigue llamando a la función condicional y la función WSAAccept funciona correctamente, pero las aplicaciones de servidor que dependen de los clientes que no pueden realizar el protocolo de enlace no funcionarán correctamente.
 
Nota Al emitir una llamada de Winsock de bloqueo como WSAAccept, 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 en curso en el mismo subproceso provocará un comportamiento indefinido y los clientes winsock nunca deben intentarlo.
 

código de ejemplo de

En el ejemplo siguiente se muestra el uso de la función
WSAAccept.
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>

/* Define an example conditional function that depends on the pQos field */
int CALLBACK ConditionAcceptFunc(
    LPWSABUF lpCallerId,
    LPWSABUF lpCallerData,
    LPQOS pQos,
    LPQOS lpGQOS,
    LPWSABUF lpCalleeId,
    LPWSABUF lpCalleeData,
    GROUP FAR * g,
    DWORD_PTR dwCallbackData
    )
{

    if (pQos != NULL) {
        RtlZeroMemory(pQos, sizeof(QOS));
        return CF_ACCEPT;
    } else
        return CF_REJECT;
}

int main() {

    /* Declare and initialize variables */
    WSADATA wsaData;
    SOCKET ListenSocket, AcceptSocket;
    struct sockaddr_in saClient;
    int iClientSize = sizeof(saClient);
    u_short port = 27015;
    char* ip;
    sockaddr_in service;
    int error;

    /* Initialize Winsock */
    error = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (error) {
        printf("WSAStartup() failed with error: %d\n", error);
        return 1;
    }

    /* Create a TCP listening socket */
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {  
        printf("socket() failed with error: %d\n", WSAGetLastError() );
        WSACleanup();
        return 1;
    }

    /*-----------------------------------------  
     *  Set up the sock addr structure that the listening socket
     *  will be bound to. In this case, the structure holds the
     * local IP address and the port specified. */
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    hostent* thisHost;
    thisHost = gethostbyname("");
    ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
    service.sin_addr.s_addr = inet_addr(ip);

    /*-----------------------------------------
     *  Bind the listening socket to the IP address.
     * and port number specified by the sockaddr structure. */
    error = bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
    if (error == SOCKET_ERROR) {  
        printf("bind() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
  
    /* Make the socket listen for incoming connection requests */
    error = listen(ListenSocket, 1);
    if (error == SOCKET_ERROR) {  
        printf("listen() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    printf("Listening...\n");
  
    /*-----------------------------------------
     *  Accept an incoming connection request on the
     *  listening socket and transfer control to the 
     * accepting socket. */
    AcceptSocket = WSAAccept(ListenSocket, (SOCKADDR*) &saClient, &iClientSize, 
        &ConditionAcceptFunc, NULL);
 
    /*  Now do some work with the AcceptSocket 
     *  At this point, the application could
     *  handle data transfer on the socket, or other socket
     * functionality.*/
    
    /* Then clean up and quit */

    closesocket(AcceptSocket);
    closesocket(ListenSocket);
    WSACleanup();

    return 0;
}

Windows Phone 8: Esta función es compatible con las aplicaciones de Windows Phone Store en Windows Phone 8 y versiones posteriores.

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

Requisitos

Requisito Valor
cliente mínimo admitido Windows 8.1, Windows Vista [aplicaciones de escritorio | Aplicaciones para UWP]
servidor mínimo admitido Windows Server 2003 [aplicaciones de escritorio | Aplicaciones para UWP]
de la plataforma de destino de Windows
encabezado de winsock2.h
biblioteca de Ws2_32.lib
DLL de Ws2_32.dll

Consulte también

WSAAsyncSelect

WSAConnect

WSASocket

funciones winsock

de referencia de Winsock

aceptar

enlazar

conectar

getockopt

de escucha

seleccionar

sockaddr

de socket de