Partager via


Fonction WSAAccept (winsock2.h)

La fonction WSAAccept accepte conditionnellement une connexion en fonction de la valeur de retour d’une fonction de condition, fournit une qualité des spécifications de flux de service et permet le transfert de données de connexion.

Syntaxe

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

Paramètres

[in] s

Descripteur qui identifie un socket qui écoute les connexions après un appel à la fonction écouter.

[out] addr

Pointeur facultatif vers une structure sockaddr qui reçoit l’adresse de l’entité de connexion, telle qu’appelée couche de communications. Le format exact du paramètre addr est déterminé par la famille d’adresses établie lors de la création du socket.

[in, out] addrlen

Pointeur facultatif vers un entier qui contient la longueur du structure sockaddr pointée par le paramètre addr, en octets.

[in] lpfnCondition

Adresse d’une fonction de condition facultative spécifiée par l’application qui prendra une décision d’acceptation/rejet en fonction des informations de l’appelant transmises en tant que paramètres, et éventuellement créer ou joindre un groupe de sockets en affectant une valeur appropriée au paramètre de résultat g de cette fonction. Si ce paramètre est NULL, aucune fonction de condition n’est appelée.

[in] dwCallbackData

Les données de rappel transmises à la fonction de condition spécifiée par l’application comme valeur du paramètre dwCallbackData passé à la fonction de condition. Ce paramètre s’applique uniquement si le paramètre lpfnCondition n’est pas NULL. Ce paramètre n’est pas interprété par Windows Sockets.

Valeur de retour

Si aucune erreur ne se produit, WSAAccept retourne une valeur de type SOCKET qui est un descripteur pour le socket accepté. Sinon, une valeur de INVALID_SOCKET est retournée et un code d’erreur spécifique peut être récupéré en appelant WSAGetLastError.

L’entier référencé par addrlen contient initialement la quantité d’espace pointée par addr. Lors du retour, elle contiendra la longueur réelle en octets de l’adresse retournée.

Code d’erreur Signification
WSAEACCES
Une tentative a été effectuée pour accéder à un socket d’une manière interdite par ses autorisations d’accès. Cette erreur est retournée si la demande de connexion qui a été proposée a expiré ou a été retirée.
WSAECONNREFUSED
Aucune connexion n’a pu être établie, car l’ordinateur cible l’a activement refusé. Cette erreur est retournée si la demande de connexion a été rejetée avec force, comme indiqué dans la valeur de retour de la fonction de condition (CF_REJECT).
WSAECONNRESET
Une connexion existante a été fermée de force par l’hôte distant. Cette erreur est retournée d’une connexion entrante a été indiquée, mais a été arrêtée par l’homologue distant avant d’accepter l’appel.
WSAEFAULT
Le système a détecté une adresse de pointeur non valide lors de la tentative d’utilisation d’un argument de pointeur dans un appel. Cette erreur est retournée du paramètre addrlen est trop petite ou le du module complémentaire ou lpfnCondition ne fait pas partie de l’espace d’adressage de l’utilisateur.
WSAEINTR
Une opération de blocage a été interrompue par un appel à WSACancelBlockingCall. Cette erreur est retournée si un appel Windows Sockets 1.1 bloquant a été annulé via WSACancelBlockingCall.
WSAEINPROGRESS
Une opération de blocage est en cours d’exécution. Cette erreur est retournée si un appel Windows Sockets 1.1 bloquant est en cours.
WSAEINVAL
Un argument non valide a été fourni. Cette erreur est retournée si écouter n’a pas été appelée avant WSAAccept , la valeur de retour de la fonction de condition n’est pas valide ou si le socket spécifié est dans un état non valide.
WSAEMFILE
Trop de sockets ouverts. Cette erreur est retournée si la file d’attente n’est pas vide lors de l’entrée à WSAAccept et qu’aucun descripteur de socket n’est disponible.
WSAENETDOWN
Une opération de socket a rencontré un réseau mort. Cette erreur est retournée si le sous-système réseau a échoué.
WSAENOBUFS
Une opération sur un socket n’a pas pu être effectuée, car le système n’a pas suffisamment d’espace tampon ou parce qu’une file d’attente était pleine. Cette erreur est retournée si aucun espace tampon n’est disponible.
WSAENOTSOCK
Une opération a été tentée sur quelque chose qui n’est pas un socket. Cette erreur est retournée si le descripteur de socket passé dans le paramètre de n’est pas un socket.
WSAEOPNOTSUPP
La famille de protocoles n’a pas été configurée dans le système ou aucune implémentation n’existe. Cette erreur est retournée si le socket référencé n’est pas un type qui prend en charge le service orienté connexion.
WSAEWOULDBLOCK
Une opération de socket non bloquante n’a pas pu être effectuée immédiatement. Cette erreur est retournée si le socket est marqué comme non bloquant et qu’aucune connexion n’est présente pour être acceptée.
WSANOTINITIALISED
L’application n’a pas appelé WSAStartup, ou WSAStartup a échoué. Cette erreur est renvoyée d’un appel réussi à la fonction WSAStartup ne se produit pas avant d’utiliser cette fonction.
WSATRY_AGAIN
Il s’agit généralement d’une erreur temporaire lors de la résolution du nom d’hôte et signifie que le serveur local n’a pas reçu de réponse d’un serveur faisant autorité. Cette erreur est retournée si l’acceptation de la demande de connexion a été différée, comme indiqué dans la valeur de retour de la fonction de condition (CF_DEFER).

Remarques

La fonction WSAAccept extrait la première connexion de la file d’attente des connexions en attente sur ledu socket , et la vérifie par rapport à la fonction de condition, à condition que la fonction de condition soit spécifiée (autrement dit, pas NULL). Si la fonction de condition retourne CF_ACCEPT, WSAAccept crée un socket. Le socket nouvellement créé a les mêmes propriétés que les de socket , y compris les événements asynchrones enregistrés avec WSAAsyncSelect ou avec WSAEventSelect. Si la fonction de condition retourne CF_REJECT, WSAAccept rejette la demande de connexion. La fonction condition s’exécute dans le même thread que cette fonction et doit retourner le plus tôt possible. Si la décision ne peut pas être prise immédiatement, la fonction condition doit retourner CF_DEFER pour indiquer qu’aucune décision n’a été prise et qu’aucune action concernant cette demande de connexion doit être prise par le fournisseur de services. Lorsque l’application est prête à prendre des mesures sur la demande de connexion, elle appelle WSAAccept à nouveau et retourne CF_ACCEPT ou CF_REJECT comme valeur de retour de la fonction de condition.

Un socket en mode par défaut (blocage) se bloque jusqu’à ce qu’une connexion soit présente lorsqu’une application appelle WSAAccept et aucune connexion n’est en attente dans la file d’attente.

Un socket en mode non bloquant (blocage) échoue avec l’erreur WSAEWOULDBLOCK lorsqu’une application appelle WSAAccept et aucune connexion n’est en attente dans la file d’attente. Une fois WSAAccept réussit et retourne un nouveau handle de socket, le socket accepté ne peut pas être utilisé pour accepter plus de connexions. Le socket d’origine reste ouvert et écoute les nouvelles demandes de connexion.

Le paramètre addr est un paramètre de résultat qui est rempli avec l’adresse de l’entité de connexion, tel qu’appelé couche de communications. Le format exact du paramètre addr est déterminé par la famille d’adresses dans laquelle la communication se produit. Le addrlen est un paramètre value-result ; il doit initialement contenir la quantité d’espace pointée par addr. Au retour, il contiendra la longueur réelle (en octets) de l’adresse retournée. Cet appel est utilisé avec des types de sockets orientés connexion tels que SOCK_STREAM. Si addr et/ou addrlen sont égaux à NULL, aucune information sur l’adresse distante du socket accepté n’est retournée. Dans le cas contraire, ces deux paramètres sont renseignés si la connexion est acceptée avec succès.

Un prototype de la fonction de condition est défini dans le fichier d’en-tête Winsock2.h comme LPCONDITIONPROC, comme suit.

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

Le ConditionFunc est un espace réservé pour la fonction de rappel spécifiée par l’application. La fonction de condition réelle doit résider dans une DLL ou un module d’application. Il est exporté dans le fichier de définition de module.

Le paramètre lpCallerId pointe vers une structure WSABUF qui contient l’adresse de l’entité de connexion, où son paramètre len est la longueur de la mémoire tampon en octets, et son paramètre de buf est un pointeur vers la mémoire tampon. L'lpCallerData est un paramètre de valeur qui contient toutes les données utilisateur. Les informations contenues dans ces paramètres sont envoyées avec la demande de connexion. Si aucune donnée d’identification ou d’appelant n’est disponible, les paramètres correspondants sont NULL. De nombreux protocoles réseau ne prennent pas en charge les données d’appelant au moment de la connexion. La plupart des protocoles réseau conventionnels peuvent être censés prendre en charge les informations d’identificateur de l’appelant au moment de la demande de connexion. La partie buf de la WSABUF pointée par lpCallerId pointe vers une sockaddr. La structure sockaddr est interprétée en fonction de sa famille d’adresses (généralement en faisant passer le sockaddr à un type spécifique à la famille d’adresses).

Le paramètre lpSQOS fait référence aux structures FLOWSPEC pour les de socket spécifiées par l’appelant, une pour chaque direction, suivie de tous les paramètres supplémentaires spécifiques au fournisseur. Les valeurs de spécification de flux d’envoi ou de réception sont ignorées en fonction des sockets unidirectionnels. Une valeur NULL indique qu’il n’existe aucune qualité de service fournie par l’appelant et qu’aucune négociation n’est possible. Un pointeur denulllpSQOS indique qu’une qualité de négociation de service doit se produire ou que le fournisseur est prêt à accepter la qualité de la demande de service sans négociation.

Le paramètre lpGQOS est réservé et doit être NULL. (réservé pour une utilisation ultérieure avec des groupes de sockets) fait référence à la structure FLOWSPEC pour le groupe de sockets que l’appelant doit créer, une pour chaque direction, suivie de paramètres supplémentaires spécifiques au fournisseur. Une valeur de NULL pour lpGQOS indique qu’aucune qualité de service de groupe spécifiée par l’appelant n’est indiquée. Les informations de qualité de service peuvent être retournées si la négociation doit se produire.

L'lpCalleeId est un paramètre qui contient l’adresse locale de l’entité connectée. La partie du WSABUF pointée par lpCalleeId pointe vers une structure sockaddr. La structure sockaddr est interprétée en fonction de sa famille d’adresses (généralement en faisant passer le sockaddr à un type spécifique à la famille d’adresses, comme le struct sockaddr_in).

L'lpCalleeData est un paramètre de résultat utilisé par la fonction condition pour fournir des données utilisateur à l’entité de connexion. La lpCalleeData->len contient initialement la longueur de la mémoire tampon allouée par le fournisseur de services et pointée par lpCalleeData->buf. La valeur zéro signifie que le passage de données utilisateur à l’appelant n’est pas pris en charge. La fonction de condition doit copier jusqu’à lpCalleeData->len octets de données dans lpCalleeData->buf, puis mettre à jour lpCalleeData->len pour indiquer le nombre réel d’octets transférés. Si aucune donnée utilisateur ne doit être renvoyée à l’appelant, la fonction de condition doit définir lpCalleeData->len sur zéro. Le format de toutes les données d’adresse et d’utilisateur est spécifique à la famille d’adresses à laquelle appartient le socket.

Le paramètre g est affecté dans la fonction de condition pour indiquer l’une des actions suivantes :

  • Si g est un identificateur de groupe de sockets existant, ajoutez à ce groupe, à condition que toutes les exigences définies par ce groupe soient remplies.
  • Si g = SG_UNCONSTRAINED_GROUP, créez un groupe de sockets non contraints et avez en tant que premier membre.
  • Si g = SG_CONSTRAINED_GROUP, créez un groupe de sockets contraints et avez s en tant que premier membre.
  • Si g = zéro, aucune opération de groupe n’est effectuée.
Pour les groupes sans contraintes, tous les ensembles de sockets peuvent être regroupés tant qu’ils sont pris en charge par un seul fournisseur de services. Un groupe de sockets contraints ne peut se composer que de sockets orientés connexion et nécessite que les connexions sur tous les sockets groupés soient à la même adresse sur le même hôte. Pour les groupes de sockets nouvellement créés, le nouvel identificateur de groupe peut être récupéré à l’aide de fonction getsockopt avec paramètre de niveau défini sur SOL_SOCKET et le paramètre optname défini sur SO_GROUP_ID. Un groupe de sockets et son ID de groupe de sockets associés restent valides jusqu’à ce que le dernier socket appartenant à ce groupe de sockets soit fermé. Les ID de groupe de sockets sont uniques dans tous les processus d’un fournisseur de services donné. Un groupe de sockets et son identificateur associé restent valides jusqu’à ce que le dernier socket appartenant à ce groupe de sockets soit fermé. Les identificateurs de groupe de sockets sont uniques dans tous les processus d’un fournisseur de services donné. Pour plus d’informations sur les groupes de sockets, consultez les remarques relatives aux fonctions WSASocket.

La valeur du paramètre dwCallbackData passée à la fonction de condition est la valeur passée en tant que paramètre dwCallbackData dans l’appel WSAAccept d’origine. Cette valeur est interprétée uniquement par le client Windows Socket version 2. Cela permet à un client de transmettre des informations de contexte à partir de la WSAAccept appeler le site à l’aide de la fonction de condition. Cela fournit également à la fonction de condition toutes les informations supplémentaires requises pour déterminer s’il faut accepter la connexion ou non. Une utilisation classique consiste à passer un pointeur (casté de manière appropriée) à une structure de données contenant des références à des objets définis par l’application avec lesquels ce socket est associé.

Remarque Pour protéger l’utilisation de la fonction WSAAccept contre les attaques SYN, les applications doivent effectuer des liaisons TCP complètes (SYN-SYNACK-ACK) avant de signaler la demande de connexion. La protection contre les attaques SYN de cette façon entraîne l’inopération de l’option de socket SO_CONDITIONAL_ACCEPT ; la fonction conditionnelle est toujours appelée, et la fonction WSAAccept fonctionne correctement, mais les applications serveur qui s’appuient sur les clients qui ne peuvent pas effectuer l’établissement d’une liaison ne fonctionneront pas correctement.
 
Remarque Lors de l’émission d’un appel Winsock bloquant, tel que WSAAccept, Winsock peut avoir besoin d’attendre un événement réseau avant la fin de l’appel. Winsock effectue une attente alertable dans cette situation, qui peut être interrompue par un appel de procédure asynchrone (APC) planifié sur le même thread. L’émission d’un autre appel Winsock bloquant à l’intérieur d’un APC qui a interrompu un appel Winsock bloquant en cours sur le même thread entraîne un comportement non défini et ne doit jamais être tenté par les clients Winsock.
 

exemple de code

L’exemple suivant illustre l’utilisation de la fonction 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 : Cette fonction est prise en charge pour les applications du Windows Phone Store sur Windows Phone 8 et versions ultérieures.

windows 8.1 et Windows Server 2012 R2: cette fonction est prise en charge pour les applications du Windows Store sur Windows 8.1, Windows Server 2012 R2 et versions ultérieures.

Exigences

Exigence Valeur
client minimum pris en charge Windows 8.1, Windows Vista [applications de bureau | Applications UWP]
serveur minimum pris en charge Windows Server 2003 [applications de bureau | Applications UWP]
plateforme cible Windows
d’en-tête winsock2.h
bibliothèque Ws2_32.lib
DLL Ws2_32.dll

Voir aussi

WSAsyncSelect

WSAConnect

WSASocket

fonctions Winsock

de référence Winsock

accepter

lier

connecter

getsockopt

écouter

sélectionner

sockaddr

socket