Partager via


Routines de blocage Windows Sockets 1.1 et EINPROGRESS

Un problème majeur dans le portage d’applications d’un environnement Berkeley Sockets vers un environnement Windows implique le blocage ; autrement dit, appel d’une fonction qui ne retourne pas tant que l’opération associée n’est pas terminée. Un problème se produit lorsque l’opération prend un temps arbitrairement long : un exemple est une fonction recv, qui peut bloquer jusqu’à ce que les données ont été reçues du système homologue. Le comportement par défaut dans le modèle Berkeley Sockets est destiné à un socket à fonctionner en mode bloquant, sauf si le programmeur demande explicitement que les opérations soient traitées comme non bloquantes. Les environnements Windows Sockets 1.1 n’ont pas pu supposer la planification préemptive. Par conséquent, il est fortement recommandé que les programmeurs utilisent les opérations non bloquantes (asynchrones) si possible avec Windows Sockets 1.1. Comme cela n’était pas toujours possible, les installations pseudo-bloquantes décrites ci-dessous ont été fournies.

Note

Windows Sockets 2 s’exécute uniquement sur les systèmes d’exploitation 32 bits préemptifs où les interblocages ne sont pas un problème. Les pratiques de programmation recommandées pour Windows Sockets 1.1 ne sont pas nécessaires dans Windows Sockets 2.

 

Même sur un socket bloquant, certaines fonctions ( lier, getockopt, et getpeername par exemple ) se terminent immédiatement. Il n’existe aucune différence entre un blocage et une opération de non-blocage pour ces fonctions. D’autres opérations, telles que recv, peuvent se terminer immédiatement ou prendre un temps arbitraire, en fonction de différentes conditions de transport. Lorsqu’elles sont appliquées à un socket bloquant, ces opérations sont appelées opérations de blocage. Les fonctions suivantes peuvent bloquer :

Avec Windows Sockets 1.1 1 1 1 1, une opération de blocage qui ne peut pas être terminée immédiatement est gérée par le pseudo-blocage comme suit.

Le fournisseur de services lance l’opération, puis entre une boucle dans laquelle il distribue tous les messages Windows (ce qui génère le processeur à un autre thread, si nécessaire), puis vérifie l’achèvement de la fonction Sockets Windows. Si la fonction est terminée ou si WSACancelBlockingCall a été appelée, la fonction bloquante se termine par un résultat approprié.

Un fournisseur de services doit autoriser l’installation d’une fonction de hook bloquante qui ne traite pas les messages afin d’éviter la possibilité de réinscrire les messages pendant qu’une opération de blocage est en attente. La fonction de crochet bloquante la plus simple retournerait FAUX. Si une DLL Windows Sockets dépend des messages pour l’opération interne, elle peut exécuter PeekMessage(hMyWnd...) avant d’exécuter le hook de blocage de l’application afin qu’il puisse obtenir ses messages sans affecter le reste du système.

Dans un environnement Windows Sockets 1.1 1 1 1 1 1, si un message Windows est reçu pour un processus pour lequel une opération de blocage est en cours, il existe un risque que l’application tente d’émettre un autre appel Windows Sockets. En raison de la difficulté de gérer cette condition en toute sécurité, Windows Sockets 1.1 ne prend pas en charge ce comportement d’application. Une application n’est pas autorisée à effectuer plusieurs appels de fonction Windows Sockets imbriqués. Un seul appel de fonction en attente est autorisé pour une tâche particulière. Les seules exceptions sont deux fonctions qui sont fournies pour aider le programmeur dans cette situation : WSAIsBlocking et WSACancelBlockingCall.

La fonction WSAIsBlocking peut être appelée à tout moment pour déterminer si un appel Windows Sockets 1.1 bloquant est en cours. De même, la fonction WSACancelBlockingCall peut être appelée à tout moment pour annuler un appel bloquant en cours. Toute autre imbrication des fonctions Windows Sockets échoue avec l’erreur WSAEINPROGRESS.

Il convient de souligner que cette restriction s’applique à la fois aux opérations bloquantes et non bloquantes. Pour les applications Windows Sockets 2 qui négocient la version 2.0 ou ultérieure au moment de l’appel de WSAStartup, aucune restriction sur l’imbrication des opérations se termine. Les opérations peuvent devenir imbriquées dans de rares circonstances, comme pendant une WSAAccept rappel d’acceptation conditionnelle, ou si un fournisseur de services appelle à son tour une fonction Windows Sockets 2.

Bien que ce mécanisme soit suffisant pour les applications simples, il ne peut pas prendre en charge les exigences complexes de répartition des messages d’applications plus avancées (par exemple, celles qui utilisent le modèle MDI). Pour ces applications, l’API Windows Sockets inclut la fonction WSASetBlockingHook, ce qui permet à l’application de spécifier une routine spéciale qui peut être appelée au lieu de la routine de distribution de messages par défaut décrite dans la discussion précédente.

Le fournisseur Windows Sockets appelle le hook bloquant uniquement si toutes les valeurs suivantes sont vraies :

  • La routine est celle qui est définie comme étant capable de bloquer.
  • Le socket spécifié est un socket bloquant.
  • La demande ne peut pas être effectuée immédiatement.

Un socket est défini sur le blocage par défaut, mais la fonction ioctlsocket avec le FIONBIO IOCTL ou la fonction WSAsyncSelect peut définir un socket en mode non bloquant.

Le hook de blocage n’est jamais appelé et l’application n’a pas besoin d’être concernée par les problèmes de réintérance que le hook de blocage peut introduire, si une application suit ces instructions :

  • Il utilise uniquement des sockets non bloquants.
  • Il utilise les routines WSAsyncSelect et/ou WSAAsyncGetXByY au lieu de sélectionner et les routines getXbyY .

Si une application Windows Sockets 1.1 appelle une opération asynchrone ou non bloquante qui prend un pointeur vers un objet mémoire (une mémoire tampon ou une variable globale, par exemple) en tant qu’argument, il incombe à l’application de s’assurer que l’objet est disponible pour windows Sockets tout au long de l’opération. L’application ne doit pas appeler une fonction Windows susceptible d’affecter la viabilité du mappage ou de l’adresse de la mémoire impliquée.