Überlappende Eingabe/Ausgabe

Windows Sockets 2 führt überlappende E/A ein und erfordert, dass alle Transportanbieter diese Funktion unterstützen. Überlappende E/A-Vorgänge können nur für Sockets ausgeführt werden, die über die WSPSocket-Funktion mit festgelegtem WSA_FLAG_OVERLAPPED Flag erstellt wurden und dem in Windows eingerichteten Modell folgen.

Für den Empfang verwendet ein Client WSPRecv oder WSPRecvFrom , um Puffer anzugeben, in die Daten empfangen werden sollen. Wenn ein oder mehrere Puffer vor dem Empfang von Daten vom Netzwerk bereitgestellt werden, ist es möglich, dass Daten sofort beim Eintreffen in die Puffer des Benutzers eingefügt werden, um den Kopiervorgang zu vermeiden, der andernfalls auftreten würde. Wenn Daten eintreffen, wenn bereits Empfangspuffer bereitgestellt wurden, werden sie sofort in die Puffer des Benutzers kopiert. Wenn Daten eingehen, wenn keine Empfangspuffer von der Anwendung bereitgestellt wurden, greift der Dienstanbieter auf den synchronen Vorgangsstil zurück, bei dem die eingehenden Daten intern gepuffert werden, bis der Client einen Empfangsaufruf ausgibt, und stellt dadurch einen Puffer bereit, in den die Daten kopiert werden können. Eine Ausnahme wäre, wenn die Anwendung WSPSetSockOpt verwendet, um die Größe des Empfangspuffers auf Null festzulegen. In diesem instance würden zuverlässige Protokolle den Empfang von Daten nur ermöglichen, wenn Anwendungspuffer bereitgestellt wurden, und Daten in unzuverlässigen Protokollen würden verloren gehen.

Auf der Sendenseite verwenden Clients WSPSend oder WSPSendTo , um Zeiger auf gefüllte Puffer bereitzustellen, und stimmen dann zu, die Puffer in keiner Weise zu stören, bis das Netzwerk den Inhalt des Puffers verbraucht hat.

Überlappende Sende- und Empfangsanrufe werden sofort zurückgegeben. Ein Rückgabewert von 0 (null) gibt an, dass der E/A-Vorgang sofort abgeschlossen wurde und dass die entsprechende Vervollständigungsanzeige bereits erfolgt ist. Das heißt, das zugeordnete Ereignisobjekt wurde signalisiert, oder die Abschlussroutine wurde über WPUQueueApc in die Warteschlange gestellt. Ein Rückgabewert von SOCKET_ERROR in Verbindung mit dem Fehlercode WSA_IO_PENDING gibt an, dass der überlappende Vorgang erfolgreich initiiert wurde und dass eine nachfolgende Angabe bereitgestellt wird, wenn Sendepuffer verbraucht wurden oder Wenn Empfangspuffer gefüllt sind. Jeder andere Fehlercode gibt an, dass der überlappende Vorgang nicht erfolgreich initiiert wurde und dass keine Vervollständigungsanzeige angezeigt wird.

Sowohl Sende- als auch Empfangsvorgänge können sich überlappen. Die Empfangsfunktionen können mehrmals aufgerufen werden, um Empfangspuffer zur Vorbereitung auf eingehende Daten zu posten, und die Sendefunktionen können mehrmals aufgerufen werden, um mehrere zu sendende Puffer in die Warteschlange zu stellen. Beachten Sie, dass zwar eine Reihe von überlappenden Sendepuffern in der angegebenen Reihenfolge gesendet wird, die entsprechenden Vervollständigungsangaben jedoch in einer anderen Reihenfolge auftreten können. Ebenso werden auf der Empfangsseite Puffer in der Reihenfolge ausgefüllt, in der sie bereitgestellt werden, aber Abschlussanzeigen können in einer anderen Reihenfolge auftreten.

Die Funktion zum verzögerten Abschluss von überlappenden E/A-Vorgängen ist auch für WSPIoctl verfügbar.

Bereitstellen von Vervollständigungsanzeigen

Dienstanbieter haben zwei Möglichkeiten, überlappende Vervollständigung anzugeben: Festlegen eines clientspezifischen Ereignisobjekts oder Aufrufen einer clientseitig angegebenen Vervollständigungsroutine. In beiden Fällen ist jedem überlappenden Vorgang eine Datenstruktur, WSAOVERLAPPED, zugeordnet. Diese Struktur wird vom Client zugeordnet und von ihm verwendet, um anzugeben, welches Ereignisobjekt (falls vorhanden) festgelegt werden soll, wenn der Abschluss eintritt. Die WSAOVERLAPPED-Struktur kann vom Dienstanbieter als Ort zum Speichern eines Handles für die Ergebnisse (z. B. Anzahl der übertragenen Bytes, aktualisierte Flags, Fehlercodes usw.) für einen bestimmten überlappenden Vorgang verwendet werden. Um diese Ergebnisse zu erhalten, müssen Clients WSPGetOverlappedResult aufrufen und einen Zeiger auf die entsprechende überlappende Struktur übergeben.

Wenn eine ereignisbasierte Vervollständigungsanzeige für eine bestimmte überlappende E/A-Anforderung ausgewählt wird, kann die WSPGetOverlappedResult-Routine selbst von Clients verwendet werden, um den Abschluss des überlappenden Vorgangs abzufragen oder auf den Abschluss des überlappenden Vorgangs zu warten. Wenn abschlussroutinenbasierte Vervollständigungsanzeige für eine bestimmte überlappende E/A-Anforderung ausgewählt wird, ist nur die Abrufoption WSPGetOverlappedResult verfügbar. Ein Client kann auch andere Mittel verwenden, um zu warten (z. B. WSAWaitForMultipleEvents), bis das entsprechende Ereignisobjekt signalisiert oder die angegebene Vervollständigungsroutine vom Dienstanbieter aufgerufen wurde. Nachdem der Abschluss angegeben wurde, kann der Client WSPGetOverlappedResult aufrufen, mit der Erwartung, dass der Aufruf sofort abgeschlossen wird.

Aufrufen von Socket-E/A-Vervollständigungsroutinen

Wenn der lpCompletionRoutine-Parameter für einen überlappenden Vorgang nicht NULL ist, liegt es in der Verantwortung des Dienstanbieters, den Aufruf der clientseitig angegebenen Vervollständigungsroutine zu veranlassen, wenn der überlappende Vorgang abgeschlossen ist. Da die Vervollständigungsroutine im Kontext desselben Threads ausgeführt werden muss, der den überlappenden Vorgang initiiert hat, kann sie nicht direkt vom Dienstanbieter aufgerufen werden. Die Ws2_32.DLL bietet einen APC-Mechanismus (asynchroner Prozeduraufruf), um den Aufruf von Abschlussroutinen zu erleichtern.

Ein Dienstanbieter sorgt dafür, dass eine Funktion im richtigen Thread ausgeführt wird, indem WPUQueueApc aufgerufen wird. Diese Funktion kann aus jedem Prozess- und Threadkontext aufgerufen werden, sogar aus einem anderen Kontext als dem Thread und Prozess, der zum Initiieren des überlappenden Vorgangs verwendet wurde.

WPUQueueApc verwendet als Eingabeparameter einen Zeiger auf eine WSATHREADID-Struktur , einen Zeiger auf eine aufzurufende APC-Funktion und einen 32-Bit-Kontextwert, der anschließend an die APC-Funktion übergeben wird. Dienstanbieter werden immer mit einem Zeiger auf die richtige WSATHREADID-Struktur über den lpThreadId-Parameter auf die überlappende Funktion bereitgestellt. Der Anbieter sollte die WSATHREADID-Struktur lokal speichern und einen Zeiger auf diese Kopie der WSATHREADID-Struktur als Eingabeparameter für WPUQueueApc bereitstellen. Sobald die WPUQueueApc-Funktion zurückgegeben wird, kann der Anbieter seine Kopie der WSATHREADID verwerfen.

Die Prozedur WPUQueueApc stellt einfach genügend Informationen in die Warteschlange, um die angegebene APC-Funktion mit den angegebenen Parametern aufzurufen, ruft sie jedoch nicht auf. Wenn der Zielthread in einen warnbaren Wartezustand wechselt, werden diese Informationen aus der Warteschlange entfernt, und ein Aufruf der APC-Funktion in diesem Zielthread und Prozesskontext erfolgt. Da der APC-Mechanismus nur einen einzelnen 32-Bit-Kontextwert unterstützt, kann die APC-Funktion selbst nicht die vom Client angegebene Vervollständigungsroutine sein, die mehr Parameter umfasst. Der Dienstanbieter muss stattdessen einen Zeiger auf seine eigene APC-Funktion bereitstellen, die den angegebenen Kontextwert verwendet, um auf die erforderlichen Ergebnisinformationen für den überlappenden Vorgang zuzugreifen, und dann die vom Client angegebene Vervollständigungsroutine aufruft.

Für Dienstanbieter, bei denen eine Benutzermoduskomponente überlappende E/A-Vorgänge implementiert, wird der APC-Mechanismus in der Regel wie folgt verwendet:

  • Wenn der E/A-Vorgang abgeschlossen ist, ordnet der Anbieter einen kleinen Puffer zu und packt ihn mit einem Zeiger auf die vom Client bereitgestellte Vervollständigungsprozedur und Parameterwerte, die an die Prozedur übergeben werden sollen.
  • Er stellt einen APC in die Warteschlange und gibt den Zeiger auf den Puffer als Kontextwert und eine eigene Zwischenprozedur als Zielprozedur an.
  • Wenn der Zielthread schließlich in den warnbaren Wartezustand wechselt, wird die Zwischenprozedur des Dienstanbieters im richtigen Threadkontext aufgerufen.
  • Die zwischengeschaltete Prozedur entpackt einfach Parameter, hebt die Zuordnung des Puffers auf und ruft die vom Client bereitgestellte Vervollständigungsprozedur auf.
  • Bei Dienstanbietern, bei denen eine Kernelmoduskomponente überlappende E/A-Vorgänge implementiert, ist eine typische Implementierung ähnlich, mit der Ausnahme, dass die Implementierung Standard-Kernelschnittstellen verwendet, um den APC in die Warteschlange zu stellen.

Die Beschreibung der relevanten Kernelschnittstellen liegt außerhalb des Geltungsbereichs der Windows Sockets 2-Spezifikation.

Hinweis

Dienstanbieter müssen Windows Sockets 2-Clients erlauben, Sende- und Empfangsvorgänge aus dem Kontext der Socket-E/A-Vervollständigungsroutine aufzurufen und sicherzustellen, dass E/A-Abschlussroutinen für einen bestimmten Socket nicht geschachtelt werden.

 

Unter bestimmten Umständen muss ein mehrstufiger Dienstanbieter möglicherweise überlappende Vorgänge innerhalb eines internen Workerthreads initiieren und abschließen. In diesem Fall wäre eine WSATHREADID von einem eingehenden Funktionsaufruf nicht verfügbar. Die Dienstanbieterschnittstelle stellt einen Upcall( WPUOpenCurrentThread) bereit, um eine WSATHREADID für den aktuellen Thread abzurufen. Wenn diese WSATHREADID nicht mehr benötigt wird, sollten ihre Ressourcen durch Aufrufen von WPUCloseThread zurückgegeben werden.