Entrée/sortie superposée

Windows Sockets 2 introduit des E/S qui se chevauchent et nécessite que tous les fournisseurs de transport prennent en charge cette fonctionnalité. Les E/S qui se chevauchent peuvent être effectuées uniquement sur les sockets créés via la fonction WSPSocket avec l’indicateur WSA_FLAG_OVERLAPPED défini, et suivre le modèle établi dans Windows.

Pour la réception, un client utilise WSPRecv ou WSPRecvFrom pour fournir des mémoires tampons dans lesquelles les données doivent être reçues. Si une ou plusieurs mémoires tampons sont publiées avant l’heure à laquelle les données ont été reçues par le réseau, il est possible que les données soient placées dans les mémoires tampons de l’utilisateur immédiatement lorsqu’elles arrivent et évitent ainsi l’opération de copie qui se produirait autrement. Si des données arrivent lorsque des mémoires tampons de réception ont déjà été publiées, elles sont copiées immédiatement dans les mémoires tampons de l’utilisateur. Si des données arrivent quand aucune mémoire tampon de réception n’a été publiée par l’application, le fournisseur de services a recours au style d’opération synchrone où les données entrantes sont mises en mémoire tampon en interne jusqu’à ce que le client émet un appel de réception et fournisse ainsi une mémoire tampon dans laquelle les données peuvent être copiées. Une exception à cela serait si l’application utilisait WSPSetSockOpt pour définir la taille de la mémoire tampon de réception sur zéro. Dans cette instance, les protocoles fiables n’autorisent la réception de données que lorsque des mémoires tampons d’application ont été publiées, et les données sur les protocoles non fiables sont perdues.

Du côté de l’envoi, les clients utilisent WSPSend ou WSPSendTo pour fournir des pointeurs vers les mémoires tampons remplies, puis acceptent de ne pas déranger les mémoires tampons de quelque manière que ce soit tant que le réseau n’a pas consommé le contenu de la mémoire tampon.

Les appels d’envoi et de réception qui se chevauchent retournent immédiatement. Une valeur de retour égale à zéro indique que l’opération d’E/S s’est terminée immédiatement et que l’indication d’achèvement correspondante s’est déjà produite. Autrement dit, l’objet d’événement associé a été signalé ou la routine d’achèvement a été mise en file d’attente via WPUQueueApc. Une valeur de retour de SOCKET_ERROR associée à un code d’erreur de WSA_IO_PENDING indique que l’opération superposée a été correctement lancée et qu’une indication ultérieure sera fournie lorsque les mémoires tampons d’envoi ont été consommées ou lorsque les mémoires tampons de réception sont remplies. Tout autre code d’erreur indique que l’opération superposée n’a pas été correctement lancée et qu’aucune indication d’achèvement ne sera disponible.

Les opérations d’envoi et de réception peuvent se chevaucher. Les fonctions de réception peuvent être appelées plusieurs fois pour publier des mémoires tampons de réception en préparation des données entrantes, et les fonctions d’envoi peuvent être appelées plusieurs fois pour mettre en file d’attente plusieurs mémoires tampons à envoyer. Notez qu’une série de mémoires tampons d’envoi qui se chevauchent sont envoyées dans l’ordre fourni, mais que les indications d’achèvement correspondantes peuvent se produire dans un ordre différent. De même, du côté récepteur, les mémoires tampons sont remplies dans l’ordre dans lequel elles sont fournies, mais les indications d’achèvement peuvent se produire dans un ordre différent.

La fonctionnalité d’achèvement différée des E/S qui se chevauchent est également disponible pour WSPIoctl.

Fournir des indications d’achèvement

Les fournisseurs de services ont deux façons d’indiquer l’achèvement qui se chevauche : définir un objet d’événement spécifié par le client ou appeler une routine d’achèvement spécifiée par le client. Dans les deux cas, une structure de données, WSAOVERLAPPED, est associée à chaque opération qui se chevauche. Cette structure est allouée par le client et utilisée par celui-ci pour indiquer quel objet d’événement (le cas échéant) doit être défini lorsque l’achèvement se produit. La structure WSAOVERLAPPED peut être utilisée par le fournisseur de services comme emplacement pour stocker un handle dans les résultats (par exemple, nombre d’octets transférés, indicateurs mis à jour, codes d’erreur, etc.) pour une opération particulière qui se chevauche. Pour obtenir ces résultats, les clients doivent appeler WSPGetOverlappedResult, en passant un pointeur vers la structure correspondante superposée.

Si l’indication d’achèvement basée sur les événements est sélectionnée pour une demande d’E/S particulière qui se chevauche, la routine WSPGetOverlappedResult peut elle-même être utilisée par les clients pour interroger ou attendre l’achèvement de l’opération qui se chevauche. Si l’indication d’achèvement basée sur la routine d’achèvement est sélectionnée pour une demande d’E/S chevauchée, seule l’option d’interrogation de WSPGetOverlappedResult est disponible. Un client peut également utiliser d’autres moyens pour attendre (comme l’utilisation de WSAWaitForMultipleEvents) jusqu’à ce que l’objet d’événement correspondant ait été signalé ou que la routine d’achèvement spécifiée ait été appelée par le fournisseur de services. Une fois l’achèvement indiqué, le client peut appeler WSPGetOverlappedResult, en s’attendant à ce que l’appel se termine immédiatement.

Appel des routines d’achèvement des E/S du socket

Si le paramètre lpCompletionRoutine d’une opération qui se chevauche n’est pas NULL, il incombe au fournisseur de services d’organiser l’appel de la routine d’achèvement spécifiée par le client lorsque l’opération superposée se termine. Étant donné que la routine d’achèvement doit être exécutée dans le contexte du même thread que celui qui a lancé l’opération superposée, elle ne peut pas être appelée directement à partir du fournisseur de services. Le Ws2_32.DLL offre un mécanisme d’appel de procédure asynchrone (APC) pour faciliter l’appel des routines d’achèvement.

Un fournisseur de services organise l’exécution d’une fonction dans le thread approprié en appelant WPUQueueApc. Cette fonction peut être appelée à partir de n’importe quel contexte de processus et de thread, même dans un contexte différent du thread et du processus utilisé pour lancer l’opération qui se chevauche.

WPUQueueApc prend comme paramètres d’entrée un pointeur vers une structure WSATHREADID , un pointeur vers une fonction APC à appeler et une valeur de contexte 32 bits qui est ensuite passée à la fonction APC. Les fournisseurs de services sont toujours fournis avec un pointeur vers la structure WSATHREADID appropriée via le paramètre lpThreadId vers la fonction qui se chevauche. Le fournisseur doit stocker la structure WSATHREADID localement et fournir un pointeur vers cette copie de la structure WSATHREADID en tant que paramètre d’entrée pour WPUQueueApc. Une fois que la fonction WPUQueueApc est retournée, le fournisseur peut supprimer sa copie de WSATHREADID.

La procédure WPUQueueApc met simplement en file d’attente suffisamment d’informations pour appeler la fonction APC indiquée avec les paramètres donnés, mais ne l’appelle pas. Lorsque le thread cible entre dans un état d’attente pouvant être alerté, ces informations sont supprimées et un appel est effectué à la fonction APC dans ce contexte de thread et de processus cible. Étant donné que le mécanisme APC ne prend en charge qu’une seule valeur de contexte 32 bits, la fonction APC ne peut pas être elle-même la routine d’achèvement spécifiée par le client, ce qui implique davantage de paramètres. Le fournisseur de services doit à la place fournir un pointeur vers sa propre fonction APC qui utilise la valeur de contexte fournie pour accéder aux informations de résultat nécessaires pour l’opération qui se chevauche, puis appelle la routine d’achèvement spécifiée par le client.

Pour les fournisseurs de services où un composant en mode utilisateur implémente des E/S superposées, une utilisation classique du mécanisme APC est la suivante :

  • Une fois l’opération d’E/S terminée, le fournisseur alloue une petite mémoire tampon et l’empaquet avec un pointeur vers la procédure d’achèvement fournie par le client et les valeurs de paramètres à passer à la procédure.
  • Il met en file d’attente un APC, en spécifiant le pointeur vers la mémoire tampon comme valeur de contexte et sa propre procédure intermédiaire en tant que procédure cible.
  • Lorsque le thread cible passe finalement à l’état d’attente pouvant être alerté, la procédure intermédiaire du fournisseur de services est appelée dans le contexte de thread approprié.
  • La procédure intermédiaire décompresse simplement les paramètres, libère la mémoire tampon et appelle la procédure d’achèvement fournie par le client.
  • Pour les fournisseurs de services où un composant en mode noyau implémente des E/S qui se chevauchent, une implémentation classique est similaire, sauf que l’implémentation utilise des interfaces de noyau standard pour mettre en file d’attente l’APC.

La description des interfaces de noyau pertinentes n’entre pas dans le cadre de la spécification Windows Sockets 2.

Notes

Les fournisseurs de services doivent autoriser les clients Windows Sockets 2 à appeler des opérations d’envoi et de réception à partir du contexte de la routine d’achèvement d’E/S de socket et garantir que pour un socket donné, les routines d’achèvement d’E/S ne seront pas imbriquées.

 

Dans certaines circonstances, un fournisseur de services en couches peut avoir besoin de lancer et d’effectuer des opérations qui se chevauchent à partir d’un thread de travail interne. Dans ce cas, un WSATHREADID ne serait pas disponible à partir d’un appel de fonction entrant. L’interface du fournisseur de services fournit un upcall, WPUOpenCurrentThread, pour obtenir un WSATHREADID pour le thread actuel. Lorsque ce WSATHREADID n’est plus nécessaire, ses ressources doivent être retournées en appelant WPUCloseThread.