WSAEventSelect-Funktion (winsock2.h)

Die WSAEventSelect-Funktion gibt ein Ereignisobjekt an, das dem angegebenen Satz von FD_XXX Netzwerkereignissen zugeordnet werden soll.

Syntax

int WSAAPI WSAEventSelect(
  [in] SOCKET   s,
  [in] WSAEVENT hEventObject,
  [in] long     lNetworkEvents
);

Parameter

[in] s

Ein Deskriptor, der den Socket identifiziert.

[in] hEventObject

Ein Handle, das das Ereignisobjekt identifiziert, das dem angegebenen Satz von FD_XXX Netzwerkereignissen zugeordnet werden soll.

[in] lNetworkEvents

Eine Bitmaske, die die Kombination aus FD_XXX Netzwerkereignissen angibt, an denen die Anwendung Interesse hat.

Rückgabewert

Der Rückgabewert ist null, wenn die Anwendungsspezifikation der Netzwerkereignisse und des zugeordneten Ereignisobjekts erfolgreich war. Andernfalls wird der Wert SOCKET_ERROR zurückgegeben, und eine bestimmte Fehlernummer kann durch Aufrufen von WSAGetLastError abgerufen werden.

Wie bei den Funktionen select und WSAAsyncSelect wird WSAEventSelect häufig verwendet, um zu bestimmen, wann ein Datenübertragungsvorgang (senden oder recv) mit der Erwartung eines sofortigen Erfolgs ausgegeben werden kann. Dennoch muss eine robuste Anwendung auf die Möglichkeit vorbereitet sein, dass das Ereignisobjekt festgelegt wird, und sie gibt einen Windows Sockets-Aufruf aus, der WSAEWOULDBLOCK sofort zurückgibt. Beispielsweise ist die folgende Abfolge von Vorgängen möglich:

  • Daten werden in Sockets eintreffen; Windows Sockets legt das WSAEventSelect-Ereignisobjekt fest.
  • Die Anwendung führt eine andere Verarbeitung durch.
  • Während der Verarbeitung gibt die Anwendung ein ioctlsocket(s, FIONREAD...) aus und stellt fest, dass Daten gelesen werden können.
  • Die Anwendung gibt eine(n,...) aus, um die Daten zu lesen.
  • Die Anwendung wartet schließlich auf das in WSAEventSelect angegebene Ereignisobjekt, das sofort zurückgibt, was angibt, dass die Daten lesebereit sind.
  • Die Anwendung gibt recv(s,...) aus, die mit dem Fehler WSAEWOULDBLOCK fehlschlägt.
Nachdem das Auftreten des Netzwerkereignisses erfolgreich aufgezeichnet wurde (indem das entsprechende Bit im internen Netzwerkereignisdatensatz festgelegt wurde) und das zugeordnete Ereignisobjekt signalisiert wurde, werden keine weiteren Aktionen für dieses Netzwerkereignis ausgeführt, bis die Anwendung den Funktionsaufruf ausführt, der die Einstellung dieses Netzwerkereignisses und die Signalisierung des zugeordneten Ereignisobjekts implizit wieder aktiviert.
Netzwerkereignis Erneutes Aktivieren der Funktion
FD_READ
Die Funktion recv, recvfrom, WSARecv, WSARecvEx oder WSARecvFrom .
FD_WRITE
Die Funktion send, sendto, WSASend oder WSASendTo .
FD_OOB
Die Funktion recv, recvfrom, WSARecv, WSARecvEx oder WSARecvFrom .
FD_ACCEPT
Die Accept-, AcceptEx- oder WSAAccept-Funktion , es sei denn, der zurückgegebene Fehlercode ist WSATRY_AGAIN, was angibt, dass die Bedingungsfunktion CF_DEFER zurückgegeben hat.
FD_CONNECT
Keine.
FD_CLOSE
Keine.
FD_QOS
Die WSAIoctl-Funktion mit befehl SIO_GET_QOS.
FD_GROUP_QOS
Reserviert.
FD_ROUTING_ INTERFACE_CHANGE
Die WSAIoctl-Funktion mit befehl SIO_ROUTING_INTERFACE_CHANGE.
FD_ADDRESS_ LIST_CHANGE
Die WSAIoctl-Funktion mit befehl SIO_ADDRESS_LIST_CHANGE.
 

Jeder Aufruf der Wiederholungsroutine, auch wenn er fehlschlägt, führt zu einer erneuten Aufzeichnung und Signalisierung für das relevante Netzwerkereignis- und Ereignisobjekt.

Für FD_READ, FD_OOB und FD_ACCEPT Netzwerkereignisse werden die Netzwerkereignisaufzeichnung und Ereignisobjektsignalisierung auf ebener Ebene ausgelöst. Dies bedeutet, dass das Netzwerkereignis aufgezeichnet und das zugeordnete Ereignisobjekt festgelegt wird, wenn die Wiederholungsroutine aufgerufen wird und die relevante Netzwerkbedingung nach dem Aufruf weiterhin gültig ist. Dies ermöglicht es einer Anwendung, ereignisgesteuert zu sein und sich nicht mit der Datenmenge zu befassen, die zu einem bestimmten Zeitpunkt eingeht. Gehen Sie dabei von der folgenden Abfolge aus:

  1. Der Transportanbieter empfängt 100 Byte Daten auf Sockets und bewirkt, dass WS2_32.DLL das FD_READ Netzwerkereignis aufzeichnen und das zugeordnete Ereignisobjekt festlegen.
  2. Die Anwendung gibt recv(s, buffptr, 50, 0) aus, um 50 Bytes zu lesen.
  3. Der Transportanbieter bewirkt, dass WS2_32.DLL das FD_READ Netzwerkereignis aufzeichnen und das zugeordnete Ereignisobjekt erneut festlegt, da noch Daten gelesen werden müssen.
Mit dieser Semantik muss eine Anwendung nicht alle verfügbaren Daten als Reaktion auf ein FD_READ Netzwerkereignis lesen– eine einzelne Recv als Reaktion auf jedes FD_READ Netzwerkereignis ist geeignet.

Das FD_QOS-Ereignis gilt als edgeauslöst. Eine Nachricht wird genau einmal gesendet, wenn eine Qualitätsänderung des Diensts auftritt. Weitere Meldungen werden erst ausgegeben, wenn der Anbieter eine weitere Änderung der Dienstqualität erkennt oder die Anwendung die Dienstqualität für den Socket neu aushandelt.

Die FD_ROUTING_INTERFACE_CHANGE- und FD_ADDRESS_LIST_CHANGE-Ereignisse werden ebenfalls als Edgeauslösung betrachtet. Eine Nachricht wird genau dann gesendet, wenn eine Änderung eintritt, nachdem die Anwendung die Benachrichtigung angefordert hat, indem WSAIoctl mit SIO_ROUTING_INTERFACE_CHANGE oder SIO_ADDRESS_LIST_CHANGE entsprechend ausgegeben wird. Andere Meldungen werden erst angezeigt, wenn die Anwendung die IOCTL erneut ausstellt und eine weitere Änderung erkannt wird, da die IOCTL ausgestellt wurde.

Wenn bereits ein Netzwerkereignis aufgetreten ist, wenn die Anwendung WSAEventSelect aufruft oder die Funktion zum erneuten Absetzen aufgerufen wird, wird ein Netzwerkereignis aufgezeichnet, und das zugeordnete Ereignisobjekt wird entsprechend festgelegt. Betrachten Sie z. B. folgendes Szenario:

  1. Eine Anwendung ruft listen auf.
  2. Eine Verbindungsanforderung wird empfangen, aber noch nicht akzeptiert.
  3. Die Anwendung ruft WSAEventSelect auf und gibt an, dass sie am FD_ACCEPT Netzwerkereignis für den Socket interessiert ist. Aufgrund der Persistenz von Netzwerkereignissen zeichnet Windows Sockets das FD_ACCEPT Netzwerkereignis auf und legt das zugeordnete Ereignisobjekt sofort fest.
Das FD_WRITE-Netzwerkereignis wird etwas anders behandelt. Ein FD_WRITE Netzwerkereignis wird aufgezeichnet, wenn ein Socket zum ersten Mal mit einem Aufruf der Funktion connect, ConnectEx, WSAConnect, WSAConnectByList oder WSAConnectByName verbunden wird oder wenn ein Socket mit der Accept-, AcceptEx- oder WSAAccept-Funktion akzeptiert wird und dann nach einem Sendefehler mit WSAEWOULDBLOCK und Pufferspeicherplatz verfügbar wird. Aus diesem Grund kann eine Anwendung davon ausgehen, dass Senden ab der ersten FD_WRITE Netzwerkereigniseinstellung möglich sind und bis ein Send WSAEWOULDBLOCK zurückgibt. Nach einem solchen Fehler findet die Anwendung heraus, dass Senden wieder möglich sind, wenn ein FD_WRITE Netzwerkereignis aufgezeichnet und das zugeordnete Ereignisobjekt festgelegt wird.

Das FD_OOB Netzwerkereignis wird nur verwendet, wenn ein Socket für den getrennten Empfang von OOB-Daten konfiguriert ist. Wenn der Socket für den Inlineempfang von OOB-Daten konfiguriert ist, werden die OOB-Daten (expedited) wie normale Daten behandelt, und die Anwendung sollte ein Interesse daran registrieren und erhält FD_READ Netzwerkereignis, nicht FD_OOB Netzwerkereignis. Eine Anwendung kann festlegen oder überprüfen, wie OOB-Daten behandelt werden sollen, indem sie setsockopt oder getsockopt für die option SO_OOBINLINE verwendet.

Der Fehlercode in einem FD_CLOSE Netzwerkereignis gibt an, ob der Socket schließen ordnungsgemäß oder abgebrochen war. Wenn der Fehlercode null ist, war das Schließen ordnungsgemäß; Wenn der Fehlercode WSAECONNRESET lautet, wurde die virtuelle Verbindung des Sockets zurückgesetzt. Dies gilt nur für verbindungsorientierte Sockets wie SOCK_STREAM.

Das FD_CLOSE Netzwerkereignis wird aufgezeichnet, wenn für die virtuelle Verbindung, die dem Socket entspricht, ein Close-Hinweis empfangen wird. In TCP bedeutet dies, dass die FD_CLOSE aufgezeichnet wird, wenn die Verbindung in den Status TIME WAIT oder CLOSE WAIT wechselt. Dies ergibt sich daraus, dass das Remote-End ein Herunterfahren auf der Sendeseite oder ein Closesocket durchführt. FD_CLOSE, die bereitgestellt wird, nachdem alle Daten aus einem Socket gelesen wurden. Ein Antrag sollte nach Erhalt der FD_CLOSE auf verbleibende Daten überprüfen, um jegliche Möglichkeit des Datenverlusts zu vermeiden. Weitere Informationen finden Sie im Abschnitt " Graceful Shutdown", "Linger-Optionen" und "Socket Closure" und die Funktion zum Herunterfahren .

Beachten Sie, dass Windows Sockets nur ein FD_CLOSE Netzwerkereignis aufzeichnen, um das Schließen einer virtuellen Verbindung anzuzeigen. Es zeichnet kein FD_READ Netzwerkereignis auf, um diese Bedingung anzugeben.

Das FD_QOS- oder FD_GROUP_QOS-Netzwerkereignis wird aufgezeichnet, wenn ein Parameter in der Flowspezifikation, die Sockets zugeordnet ist, aufgezeichnet wird. Anwendungen sollten WSAIoctl mit Befehl SIO_GET_QOS verwenden, um die aktuelle Dienstqualität für Sockets abzurufen.

Das FD_ROUTING_INTERFACE_CHANGE Netzwerkereignis wird aufgezeichnet, wenn die lokale Schnittstelle, die verwendet werden soll, um das in WSAIoctl angegebene Ziel mit SIO_ROUTING_INTERFACE_CHANGE Änderungen zu erreichen, nachdem eine solche IOCTL ausgestellt wurde.

Das FD_ADDRESS_LIST_CHANGE Netzwerkereignis wird aufgezeichnet, wenn die Liste der Adressen der Protokollfamilie für den Socket, an die die Anwendung Änderungen binden kann, nachdem WSAIoctl mit SIO_ADDRESS_LIST_CHANGE ausgestellt wurde.

Fehlercode Bedeutung
WSANOTINITIALISED Vor der Verwendung dieser Funktion muss ein erfolgreicher WSAStartup-Aufruf erfolgen.
WSAENETDOWN Fehler beim Netzwerksubsystem.
WSAEINVAL Einer der angegebenen Parameter war ungültig, oder der angegebene Socket befindet sich in einem ungültigen Zustand.
WSAEINPROGRESS Ein blockierter Windows Sockets 1.1-Aufruf wird ausgeführt, oder der Dienstanbieter verarbeitet noch eine Rückruffunktion.
WSAENOTSOCK Der Deskriptor ist kein Socket.

Hinweise

Die WSAEventSelect-Funktion wird verwendet, um ein Ereignisobjekt ( hEventObject) anzugeben, das dem ausgewählten FD_XXX Netzwerkereignissen lNetworkEvents zugeordnet werden soll. Der Socket, für den ein Ereignisobjekt angegeben ist, wird durch den s-Parameter identifiziert. Das Ereignisobjekt wird festgelegt, wenn eines der nominierten Netzwerkereignisse auftritt.

Die WSAEventSelect-Funktion funktioniert sehr ähnlich wie WSAAsyncSelect. Der Unterschied ist die Aktion, die ausgeführt wird, wenn ein nominiertes Netzwerkereignis auftritt. Die WSAAsyncSelect-Funktion bewirkt, dass eine von der Anwendung angegebene Windows-Nachricht veröffentlicht wird. WSAEventSelect legt das zugeordnete Ereignisobjekt fest und zeichnet das Vorkommen dieses Ereignisses in einem internen Netzwerkereignisdatensatz auf. Eine Anwendung kann WSAWaitForMultipleEvents verwenden, um das Ereignisobjekt abzuwarten oder abzufragen, und WSAEnumNetworkEvents verwenden, um den Inhalt des internen Netzwerkereignisdatensatzes abzurufen und somit zu bestimmen, welche der nominierten Netzwerkereignisse aufgetreten sind.

Die richtige Möglichkeit zum Zurücksetzen des Zustands eines Ereignisobjekts, das mit der WSAEventSelect-Funktion verwendet wird, besteht darin, das Handle des Ereignisobjekts an die WSAEnumNetworkEvents-Funktion im hEventObject-Parameter zu übergeben. Dadurch wird das Ereignisobjekt zurückgesetzt und die status aktiver FD-Ereignisse im Socket auf atomare Weise angepasst.

WSAEventSelect ist die einzige Funktion, die dazu führt, dass Netzwerkaktivitäten und -fehler aufgezeichnet und über WSAEnumNetworkEvents abgerufen werden können. In den Beschreibungen von select und WSAAsyncSelect erfahren Sie, wie diese Funktionen Netzwerkaktivitäten und Fehler melden.

Die WSAEventSelect-Funktion legt Sockets automatisch auf den Nichtblockierungsmodus fest, unabhängig vom Wert von lNetworkEvents. Um Sockets wieder in den Blockiermodus zu versetzen, müssen Sie zunächst den Ereignisdatensatz löschen, der Sockets zugeordnet ist, über einen Aufruf von WSAEventSelect , wobei lNetworkEvents auf null und der hEventObject-Parameter auf NULL festgelegt ist. Sie können dann ioctlsocket oder WSAIoctl aufrufen, um den Socket wieder in den Blockierungsmodus zu versetzen.

Der lNetworkEvents-Parameter wird mithilfe des bitweisen OR-Operators mit einem der in der folgenden Liste angegebenen Werte erstellt.

Wert Bedeutung
FD_READ Möchte eine Benachrichtigung über die Lesebereitschaft erhalten.
FD_WRITE Möchte eine Benachrichtigung über die Bereitschaft zum Schreiben erhalten.
FD_OOB Möchte eine Benachrichtigung über die Ankunft von OOB-Daten erhalten.
FD_ACCEPT Möchte eine Benachrichtigung über eingehende Verbindungen erhalten.
FD_CONNECT Möchte eine Benachrichtigung über den abgeschlossenen Verbindungs- oder Multipoint-Verknüpfungsvorgang erhalten.
FD_CLOSE Möchte eine Benachrichtigung über den Socketabschluss erhalten.
FD_QOS Möchte eine Benachrichtigung über Socket (QoS-Änderungen) erhalten.
FD_GROUP_QOS Reserviert für die zukünftige Verwendung mit Socketgruppen. Möchten Benachrichtigungen über QoS-Änderungen der Socketgruppe erhalten.
FD_ROUTING_ INTERFACE_CHANGE Möchte Benachrichtigungen über Änderungen der Routingschnittstelle für das angegebene Ziel erhalten.
FD_ADDRESS_ LIST_CHANGE Möchte eine Benachrichtigung über Änderungen der lokalen Adressliste für die Adressfamilie des Sockets erhalten.
 

Wenn Sie einen WSAEventSelect für einen Socket ausgeben, werden alle vorherigen WSAAsyncSelect - oder WSAEventSelect-Instanzen für denselben Socket abgebrochen und der interne Netzwerkereignisdatensatz gelöscht. Um beispielsweise ein Ereignisobjekt sowohl Lese- als auch Schreibnetzwerkereignissen zuzuordnen, muss die Anwendung WSAEventSelect sowohl mit FD_READ als auch mit FD_WRITE aufrufen, wie folgt:

rc = WSAEventSelect(s, hEventObject, FD_READ|FD_WRITE);

Es ist nicht möglich, unterschiedliche Ereignisobjekte für verschiedene Netzwerkereignisse anzugeben. Der folgende Code funktioniert nicht. Der zweite Aufruf bricht die Auswirkungen des ersten ab, und nur das FD_WRITE Netzwerkereignis wird hEventObject2 zugeordnet:

rc = WSAEventSelect(s, hEventObject1, FD_READ);
rc = WSAEventSelect(s, hEventObject2, FD_WRITE); //bad

Um die Zuordnung und Auswahl von Netzwerkereignissen auf einem Socket abzubrechen, sollte lNetworkEvents auf 0 festgelegt werden. In diesem Fall wird der hEventObject-Parameter ignoriert.

rc = WSAEventSelect(s, hEventObject, 0);

Durch das Schließen eines Sockets mit closesocket werden auch die Zuordnung und Auswahl von Netzwerkereignissen abgebrochen, die in WSAEventSelect für den Socket angegeben sind. Die Anwendung muss jedoch weiterhin WSACloseEvent aufrufen, um das Ereignisobjekt explizit zu schließen und Ressourcen freizugeben.

Der Socket, der erstellt wird, wenn die Accept-Funktion aufgerufen wird, verfügt über die gleichen Eigenschaften wie der lauschende Socket, mit dem er akzeptiert wird. Alle WSAEventSelect-Zuordnungen und Netzwerkereignisse, die für den lauschenden Socket festgelegt sind, gelten für den akzeptierten Socket. Wenn z. B. ein lauschender Socket über die WSAEventSelect-Zuordnung von hEventObject mit FD_ACCEPT, FD_READ und FD_WRITE verfügt, verfügt jeder für diesen Überwachungssocket akzeptierte Socket auch über FD_ACCEPT, FD_READ und FD_WRITE Netzwerkereignisse, die demselben hEventObject zugeordnet sind. Wenn ein anderes hEventObject - oder Netzwerkereignis gewünscht wird, sollte die Anwendung WSAEventSelect aufrufen und den akzeptierten Socket und die gewünschten neuen Informationen übergeben.

Beispielcode

Im folgenden Beispiel wird die Verwendung der WSAEventSelect-Funktion veranschaulicht.
//-------------------------
// Declare and initialize variables
SOCKET ListenSocket;
WSAEVENT NewEvent;
sockaddr_in InetAddr;

//-------------------------
// Initialize listening socket
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

//-------------------------
// Bind listening socket
InetAddr.sin_family = AF_INET;
InetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InetAddr.sin_port = htons(27015);

bind (ListenSocket, (SOCKADDR *) &InetAddr, sizeof(InetAddr));

//-------------------------
// Create new event
NewEvent = WSACreateEvent();

//-------------------------
// Associate event types FD_ACCEPT and FD_CLOSE
// with the listening socket and NewEvent
WSAEventSelect( ListenSocket, NewEvent, FD_ACCEPT | FD_CLOSE);

//----------------------
// Listen for incoming connection requests 
// on the created socket
if (listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR)
    printf("Error listening on socket.\n");

printf("Listening on socket...\n");

// Need an event handler added to handle connection requests



Windows Phone 8: Diese Funktion wird für Windows Phone Store-Apps ab Windows Phone 8 unterstützt.

Windows 8.1 und Windows Server 2012 R2: Diese Funktion wird für Windows Store-Apps auf Windows 8.1, Windows Server 2012 R2 und höher unterstützt.

Anforderungen

Anforderung Wert
Unterstützte Mindestversion (Client) Windows 8.1, Windows Vista [Desktop-Apps | UWP-Apps]
Unterstützte Mindestversion (Server) Windows Server 2003 [Desktop-Apps | UWP-Apps]
Zielplattform Windows
Kopfzeile winsock2.h
Bibliothek Ws2_32.lib
DLL Ws2_32.dll

Weitere Informationen

WSAAsyncSelect

WSACloseEvent

WSACreateEvent

WSAEnumNetworkEvents

WSAWaitForMultipleEvents

Winsock-Funktionen

Winsock-Referenz

shutdown