Socket chevauché I / O par rapport au mode de blocage / non-blocage


Résumé


Cet article explique la différence entre l'attribut I/O superposé d'une prise et le mode de blocage ou de non-blocage de la prise.

Informations supplémentaires


Lorsqu'une prise est créée, par défaut, il s'agit d'une prise de blocage. Vous pouvez utiliser la commande FIONBIO dans l'appel API ioctlsocket, WSAEventSelect ou WSAAysncSelect pour changer le mode prise de blocage à non-blocage. Si un appel Winsock ne peut pas se terminer immédiatement, l'appel échoue et WSAGetLastError renvoie une erreur WSAEWOULDBLOCK s'il s'agit d'une prise non bloquante, ou les blocs d'appel jusqu'à ce que l'opération se termine si c'est une prise de blocage. L'attribut I/O superposé de la prise est différent du mode de blocage ou de non-blocage de la prise. Bien que l'implémentation Winsock actuelle nécessite un attribut I/O superposé pour le mode de prise non bloquant, ils sont conceptuellement indépendants et leur modèle de programmation est également différent. Pour créer une prise avec l'attribut I/O superposé, vous pouvez utiliser l'API de prise ou l'API WSASocket avec l'ensemble de drapeau WSA-FLAG-OVERLAPPED. Si une opération I/O superposée ne peut pas se terminer immédiatement, l'appel échoue et WSAGetLastError ou GetLastError retour WSA-IO-PENDING ou ERROR-IO-PENDING, qui est en fait la même définir que WSA-IO-PENDING. Pour plus d'informations, veuillez consulter l'article suivant dans la base de connaissances Microsoft :
179942 INFO: WSA-FLAG-OVERLAPPED est nécessaire pour les prises non bloquantes
Veuillez noter qu'une fois qu'une prise est créée, il n'y a aucun moyen de modifier l'attribut de la prise qui se chevauche. Toutefois, vous pouvez appeler l'API sockopt avec l'option SO-OPENTYPE sur toutes les poignées de prise, y compris un INVALID-SOCKET pour modifier les attributs superposés pour tous les appels de prise successifs dans le même thread. La valeur d'option par défaut SO-OPENTYPE est 0, qui définit l'attribut superposé. Toutes les valeurs d'option non nulles rendent la prise synchrone et la rendent de sorte que vous ne puissiez pas utiliser une fonction d'achèvement. En définissant l'attribut I/O superposé d'une prise, cela ne signifie pas que la prise effectuera une opération I/O superposée. Par exemple, si vous spécifiez NULL pour la fonction d'achèvement et la structure superposée dans WSARecv et WSASend, ou si vous appelez simplement des fonctions de recv ou d'envoi, elles se complèteront de manière à bloquer. Pour vous assurer que l'I/O est effectué de façon superposée, vous devez fournir une structure superposée dans votre fonction I/O, selon la fonction que vous utilisez.

Chevauché I/O

Dans Winsock 1, vous créez une prise superposée à l'aide de l'API de prise, et utilisez Win32 fichier I/O API ReadFile, ReadFileEx, WriteFile, WriteFileEx pour effectuer l'I/O superposé sur la poignée de prise. Dans Winsock 2, vous créez une prise superposée à l'aide de WSASocket avec le drapeau WSA-FLAG-OVERLAPPED, ou tout simplement en utilisant l'API de prise. Vous pouvez utiliser les API Win/O de fichier I/O ci-dessus ou Winsock 2 WSASend, WSASendTo, WSARecv et WSARecvDe pour lancer une opération I/O superposée. Si vous utilisez l'option SO-RCVBUF et SO-SNDBUF pour définir zéro pile TCP recevoir et envoyer un tampon, vous instruisez essentiellement la pile TCP pour effectuer directement I /O en utilisant le tampon fourni dans votre appel I/O. Par conséquent, en plus de l'avantage de non-blocage de la prise superposée I / O, l'autre avantage est une meilleure performance parce que vous enregistrez une copie tampon entre le tampon de pile TCP et le tampon utilisateur pour chaque appel I / O. Mais vous devez vous assurer que vous n'accédez pas au tampon utilisateur une fois qu'il est soumis pour l'opération superposée et avant que l'opération superposée se termine. Pour déterminer si l'opération I/O superposée est terminée, vous pouvez utiliser l'une des options suivantes :
  • Vous pouvez fournir une poignée d'événement dans une structure superposée utilisée dans l'appel I/O et attendre le signal de la poignée de l'événement.
  • Utilisez GetOverlappedResult ou WSAGetOverlappedResult pour sonder l'état de l'opération I/O superposée. Sur Windows NT, vous pouvez spécifier NULL lorsque la poignée d'événement se trouve dans la structure superposée. Toutefois, sur Windows 95, la structure superposée doit contenir une poignée d'événement de réinitialisme manuel. WSAGetOverlappedResult sur Windows 98 et Windows Millennium Edition (ME) est modifié de telle sorte qu'il se comportera comme Windows NT et peut également sonder l'état d'achèvement avec une poignée d'événement NULL dans la structure superposée.
  • Utilisez ReadFileEx, WriteFileEx, WSARecv, WSARecvDe, WSASend ou WSASendTo et choisissez de fournir une fonction d'achèvement à appeler lorsque l'opération I/O superposée est terminée. Si vous utilisez l'approche de la fonction d'achèvement, à un moment donné après avoir émis l'opération I/O superposée, vous devez émettre une fonction d'attente Win32 ou une version WSA de la fonction d'attente pour attendre sur une poignée non signalée pour mettre votre thread actuel dans un état d'attente alertable. Lorsque l'opération I/O superposée se termine, votre fonction d'achèvement est appelée, votre fonction d'attente va renvoyer WAIT-IO-COMPLETION, et votre thread d'attente alertable se réveille.
  • Utilisez GetQueuedCompletionStatus et associez une prise, ainsi que l'ensemble d'attributs I/O superposé, avec un port d'achèvement Windows NT I/O (IOCP). Avec IOCP, vous n'avez pas besoin de fournir une fonction d'achèvement, d'attendre une poignée d'événement pour signaler, ou de sonder l'état de l'opération superposée. Une fois que vous avez créé l'IOCP et ajouté votre poignée de prise superposée à l'IOCP, vous pouvez démarrer l'opération superposée en utilisant l'une des API I/O mentionnées ci-dessus (sauf recv, recvfrom, send, ou sendto). Vous aurez votre bloc de thread de travail sur GetQueuedCompletionStatus API en attente d'un paquet d'achèvement I / O. Lorsqu'un I/O superposé se termine, un paquet d'achèvement I/O arrive à l'IOCP et GetQueuedCompletionStatus revient. IOCP est le système d'exploitation Windows NT pour la rédaction d'un serveur évolutif à haut débit en utilisant un code de filetage et de blocage très simple sur les opérations I/O superposées. Ainsi, il peut y avoir un avantage de performance significatif de l'utilisation de prise superposée I / O avec Windows NT IOCPs.

Mode de blocage et de non-blocage

Lorsqu'une prise est créée, par défaut, il s'agit d'une prise de blocage. Sous le mode de blocage des opérations I/O, connectez et acceptez les opérations toutes les opérations jusqu'à ce que l'opération en question soit terminée. Pour changer le mode de fonctionnement de la prise du mode de blocage au mode non-blocage, vous pouvez utiliser WSAAsyncSelect, WSAEventSelect, ou la commande FIONBIO dans l'appel API ioctlsocket. WSAAsyncSelect cartes notifications de prise aux messages Windows et est le meilleur modèle pour une seule application GUI filetée. WSAEventSelect utilise WSAEnumNetworkEvents pour déterminer la nature de la notification de prise sur l'événement de signalisation et les notifications de prise de cartes en signalant un événement. Il s'agit d'un modèle utile pour les applications non-GUI qui n'ont pas de pompe à message, comme une application de service Windows NT. La commande FIONBIO dans l'appel API ioctlsocket met également la prise en mode non-blocage. Mais vous devez sonder l'état de la prise en utilisant l'API sélectionnée. Mise à jour : La mise à jour de SO-RCVBUF à zéro avec les cv recv superposés n'est pas nécessaire pour Windows 2000, qui peut copier directement les données sur le tampon recv de l'application. Réglage SO-SNDBUF à zéro avec l'envoi superposé sur Windows 2000 a toujours le même avantage d'enregistrer une copie de mémoire que sur Windows NT 4.0. Il est également important que l'application délivre plusieurs envois ou recv en suspens si l'application définit le tampon de pile correspondant à 0.