Partager via


Windows Sockets 1.1 Bloquant les routines 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 se 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 qu’un socket fonctionne 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 ne pouvaient pas assumer la planification préemptive. Par conséquent, il était 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 pseudo-installations de blocage décrites dans la section suivante ont été fournies.

Notes

Windows Sockets 2 s’exécute uniquement sur des 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 ( bind, getsockopt et getpeername , par exemple) se terminent immédiatement. Il n’existe aucune différence entre une opération bloquante et une opération non bloquante pour ces fonctions. D’autres opérations, telles que recv, peuvent se terminer immédiatement ou prendre un temps arbitraire, en fonction des différentes conditions de transport. Lorsqu’elles sont appliquées à un socket bloquant, ces opérations sont appelées opérations bloquantes. Les fonctions suivantes peuvent bloquer :

Avec Windows Sockets 1.1 1 16 bits, une opération de blocage qui ne peut pas se terminer immédiatement est gérée par un pseudo-blocage comme suit.

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

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

Dans un environnement Windows Sockets 1.1 1 1 16 bits, 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 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 ou non. De même, la fonction WSACancelBlockingCall peut être appelée à tout moment pour annuler un appel bloquant en cours. Toute autre imbrication de fonctions Windows Sockets échoue avec l’erreur WSAEINPROGRESS.

Il convient de souligner que cette restriction s’applique 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 sorties d’opérations. Les opérations peuvent être imbriquées dans de rares circonstances, par exemple lors d’un rappel d’acceptation conditionnelle WSAAccept , 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 distribution de messages des applications plus avancées (par exemple, celles qui utilisent le modèle MDI). Pour ces applications, l’API Windows Sockets inclut la fonction WSASetBlockingHook, 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 de blocage uniquement si toutes les conditions suivantes sont remplies :

  • La routine est définie comme pouvant être bloquée.
  • Le socket spécifié est un socket bloquant.
  • La demande ne peut pas être effectuée immédiatement.

Un socket est défini sur bloquant par défaut, mais la fonction ioctlsocket avec la fonction FIONBIO IOCTL ou WSAAsyncSelect 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éintrodance que le hook de blocage peut introduire, si une application suit ces instructions :

  • Il utilise uniquement des sockets non bloquants.
  • Il utilise les routines WSAAsyncSelect et/ou WSAsyncGetXByY au lieu des routines select et 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) comme 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 appeler aucune fonction Windows susceptible d’affecter le mappage ou la viabilité de l’adresse de la mémoire impliquée.