WSAAccept-Funktion (winsock2.h)

Die WSAAccept-Funktion akzeptiert bedingt eine Verbindung basierend auf dem Rückgabewert einer Bedingungsfunktion, stellt Qualitätsspezifikationen für den Dienstfluss bereit und ermöglicht die Übertragung von Verbindungsdaten.

Syntax

SOCKET WSAAPI WSAAccept(
  [in]      SOCKET          s,
  [out]     sockaddr        *addr,
  [in, out] LPINT           addrlen,
  [in]      LPCONDITIONPROC lpfnCondition,
  [in]      DWORD_PTR       dwCallbackData
);

Parameter

[in] s

Ein Deskriptor, der einen Socket identifiziert, der nach einem Aufruf der Listenfunktion auf Verbindungen lauscht.

[out] addr

Ein optionaler Zeiger auf eine sockaddr-Struktur , die die Adresse der Verbindungsentität empfängt, wie für die Kommunikationsebene bekannt. Das genaue Format des addr-Parameters wird durch die Adressfamilie bestimmt, die beim Erstellen des Sockets eingerichtet wurde.

[in, out] addrlen

Ein optionaler Zeiger auf eine ganze Zahl, die die Länge der sockaddr-Struktur enthält, auf die der addr-Parameter in Bytes verweist.

[in] lpfnCondition

Die Adresse einer optionalen, von der Anwendung angegebenen Bedingungsfunktion, die basierend auf den als Parameter übergebenen Aufruferinformationen eine Annahme-/Ablehnungsentscheidung trifft und optional eine Socketgruppe erstellt oder verknüpft, indem sie dem Ergebnisparameter g dieser Funktion einen geeigneten Wert zuweisen. Wenn dieser Parameter NULL ist, wird keine Bedingungsfunktion aufgerufen.

[in] dwCallbackData

Rückrufdaten, die an die anwendungsspezifische Bedingungsfunktion als Wert des dwCallbackData-Parameters zurückgegeben werden, der an die Bedingungsfunktion übergeben wird. Dieser Parameter ist nur anwendbar, wenn der lpfnCondition-Parameter nicht NULL ist. Dieser Parameter wird nicht von Windows Sockets interpretiert.

Rückgabewert

Wenn kein Fehler auftritt, gibt WSAAccept einen Wert vom Typ SOCKET zurück, der ein Deskriptor für den akzeptierten Socket ist. Andernfalls wird der Wert INVALID_SOCKET zurückgegeben, und ein bestimmter Fehlercode kann durch Aufrufen von WSAGetLastError abgerufen werden.

Die ganze Zahl, auf die von addrlen verwiesen wird, enthält zunächst den Abstand, auf den addr verweist. Bei der Rückgabe enthält sie die tatsächliche Länge der zurückgegebenen Adresse in Byte.

Fehlercode Bedeutung
WSAEACCES
Der Zugriff auf einen Socket war aufgrund der Zugriffsrechte des Sockets unzulässig. Dieser Fehler wird zurückgegeben, wenn für die angebotene Verbindungsanforderung ein Timeout aufgetreten ist oder zurückgezogen wurde.
WSAECONNREFUSED
Es konnte keine Verbindung hergestellt werden, da diese vom Zielcomputer aktiv verweigert wurde . Dieser Fehler wird zurückgegeben, wenn die Verbindungsanforderung erzwungen abgelehnt wurde, wie im Rückgabewert der Bedingungsfunktion angegeben (CF_REJECT).
WSAECONNRESET
An existing connection was forcibly closed by the remote host. Dieser Fehler wird zurückgegeben, wenn eine eingehende Verbindung angezeigt wurde, die jedoch vor der Annahme des Anrufs vom Remotepeer beendet wurde.
WSAEFAULT
Das System hat beim Versuch, ein Zeigerargument in einem Aufruf zu verwenden, eine ungültige Zeigeradresse erkannt. Dieser Fehler wird zurückgegeben, da der addrlen-Parameter zu klein ist oder der addr oder lpfnCondition nicht Teil des Benutzeradressraums ist.
WSAEINTR
Ein blockierender Vorgang wurde durch einen Aufruf von WSACancelBlockingCall unterbrochen. Dieser Fehler wird zurückgegeben, wenn ein blockierender Windows Sockets 1.1-Aufruf über WSACancelBlockingCall abgebrochen wurde.
WSAEINPROGRESS
Ein Blockierungsvorgang wird momentan ausgeführt. Dieser Fehler wird zurückgegeben, wenn ein blockierter Windows Sockets 1.1-Aufruf ausgeführt wird.
WSAEINVAL
Ein ungültiges Argument wurde angegeben. Dieser Fehler wird zurückgegeben, wenn die Überwachung vor WSAAccept nicht aufgerufen wurde, der Rückgabewert der Bedingungsfunktion kein gültiger ist oder wenn sich der angegebene Socket in einem ungültigen Zustand befindet.
WSAEMFILE
Zu viele geöffnete Sockets. Dieser Fehler wird zurückgegeben, wenn die Warteschlange beim Eintritt in WSAAccept nicht leer ist und keine Socketdeskriptoren verfügbar sind.
WSAENETDOWN
Bei einem Socketvorgang war das Netzwerk inaktiv. Dieser Fehler wird zurückgegeben, wenn das Netzwerksubsystem fehlgeschlagen ist.
WSAENOBUFS
Ein Vorgang für einen Socket konnte nicht ausgeführt werden, weil dem System ausreichender Pufferspeicherplatz fehlte oder eine Warteschlange voll war. Dieser Fehler wird zurückgegeben, wenn kein Pufferspeicher verfügbar ist.
WSAENOTSOCK
Es wurde ein Vorgang für eine Komponente versucht, die kein Socket ist. Dieser Fehler wird zurückgegeben, wenn der im s-Parameter übergebene Socketdeskriptor kein Socket ist.
WSAEOPNOTSUPP
Die Protokollfamilie wurde nicht im System konfiguriert, oder es ist keine Implementierung dafür vorhanden. Dieser Fehler wird zurückgegeben, wenn der Socket, auf den verwiesen wird, kein Typ ist, der den verbindungsorientierten Dienst unterstützt.
WSAEWOULDBLOCK
Ein nicht blockierender Socketvorgang konnte nicht sofort abgeschlossen werden. Dieser Fehler wird zurückgegeben, wenn der Socket als nicht blockiert markiert ist und keine Verbindungen vorhanden sind, um akzeptiert zu werden.
WSANOTINITIALISIERT
Entweder hat die Anwendung WSAStartup nicht aufgerufen, oder WSAStartup ist fehlgeschlagen. Dieser Fehler wird von einem erfolgreichen Aufruf der WSAStartup-Funktion zurückgegeben, die vor der Verwendung dieser Funktion nicht auftritt.
WSATRY_AGAIN
Hierbei handelt es sich in der Regel um einen temporären Fehler, der während der Auflösung von Hostnamen auftritt und einen Hinweis darauf liefert, dass der lokale Server keine Antwort von einem autorisierenden Server erhalten hat. Dieser Fehler wird zurückgegeben, wenn die Annahme der Verbindungsanforderung verzögert wurde, wie im Rückgabewert der Bedingungsfunktion angegeben (CF_DEFER).

Hinweise

Die WSAAccept-Funktion extrahiert die erste Verbindung in der Warteschlange der ausstehenden Verbindungen für Sockets und überprüft sie anhand der Bedingungsfunktion, sofern die Bedingungsfunktion angegeben ist (d. h. nicht NULL). Wenn die Bedingungsfunktion CF_ACCEPT zurückgibt, erstellt WSAAccept einen neuen Socket. Der neu erstellte Socket verfügt über die gleichen Eigenschaften wie Sockets, einschließlich asynchroner Ereignisse, die mit WSAAsyncSelect oder WSAEventSelect registriert sind. Wenn die Bedingungsfunktion CF_REJECT zurückgibt, lehnt WSAAccept die Verbindungsanforderung ab. Die Bedingungsfunktion wird im selben Thread wie diese Funktion ausgeführt und sollte so schnell wie möglich zurückgegeben werden. Wenn die Entscheidung nicht sofort getroffen werden kann, sollte die Bedingungsfunktion CF_DEFER zurückgeben, um anzugeben, dass keine Entscheidung getroffen wurde, und dass keine Aktion des Dienstanbieters zu dieser Verbindungsanforderung durchgeführt werden sollte. Wenn die Anwendung bereit ist, eine Aktion für die Verbindungsanforderung auszuführen, ruft sie WSAAccept erneut auf und gibt entweder CF_ACCEPT oder CF_REJECT als Rückgabewert aus der Bedingungsfunktion zurück.

Ein Socket im Standardmodus (blockierend) wird blockiert, bis eine Verbindung vorhanden ist, wenn eine Anwendung WSAAccept aufruft und keine Verbindungen in der Warteschlange ausstehen.

Ein Socket im Nichtblockierungsmodus (Blockieren) schlägt mit dem Fehler WSAEWOULDBLOCK fehl, wenn eine Anwendung WSAAccept aufruft und keine Verbindungen in der Warteschlange ausstehen. Nachdem WSAAccept erfolgreich war und ein neues Sockethandle zurückgibt, kann der akzeptierte Socket nicht mehr verwendet werden, um weitere Verbindungen zu akzeptieren. Der ursprüngliche Socket bleibt geöffnet und lauscht auf neue Verbindungsanforderungen.

Der addr-Parameter ist ein Ergebnisparameter, der mit der Adresse der Verbindungsentität ausgefüllt wird, wie auf der Kommunikationsebene bekannt. Das genaue Format des addr-Parameters wird durch die Adressfamilie bestimmt, in der die Kommunikation stattfindet. Addrlen ist ein Wert-Ergebnis-Parameter. Sie sollte zunächst den Platz enthalten, auf den der Addr verweist. Bei der Rückgabe enthält sie die tatsächliche Länge (in Byte) der zurückgegebenen Adresse. Dieser Aufruf wird für verbindungsorientierte Sockettypen wie SOCK_STREAM verwendet. Wenn addr und/oder addrlengleich NULL sind, werden keine Informationen zur Remoteadresse des akzeptierten Sockets zurückgegeben. Andernfalls werden diese beiden Parameter ausgefüllt, wenn die Verbindung erfolgreich akzeptiert wurde.

Ein Prototyp der Bedingungsfunktion wird in der Winsock2.h Headerdatei wie folgt als LPCONDITIONPROC definiert.

int CALLBACK 
ConditionFunc( 
  IN     LPWSABUF    lpCallerId, 
  IN     LPWSABUF    lpCallerData, 
  IN OUT LPQOS       lpSQOS, 
  IN OUT LPQOS       lpGQOS,
  IN     LPWSABUF    lpCalleeId, 
  IN     LPWSABUF    lpCalleeData, 
  OUT    GROUP FAR * g, 	
  IN     DWORD_PTR   dwCallbackData
);

ConditionFunc ist ein Platzhalter für die anwendungsspezifische Rückruffunktion. Die tatsächliche Bedingungsfunktion muss sich in einer DLL oder einem Anwendungsmodul befinden. Sie wird in die Moduldefinitionsdatei exportiert.

Der parameter lpCallerId verweist auf eine WSABUF-Struktur, die die Adresse der Verbindungsentität enthält, wobei der len-Parameter die Länge des Puffers in Bytes und der buf-Parameter ein Zeiger auf den Puffer ist. LpCallerData ist ein Wertparameter, der beliebige Benutzerdaten enthält. Die Informationen in diesen Parametern werden zusammen mit der Verbindungsanforderung gesendet. Wenn keine Aufruferidentifikation oder Aufruferdaten verfügbar sind, sind die entsprechenden Parameter NULL. Viele Netzwerkprotokolle unterstützen keine Aufruferdaten zur Verbindungszeit. Von den meisten herkömmlichen Netzwerkprotokollen kann erwartet werden, dass sie Informationen zum Aufruferbezeichner zum Zeitpunkt der Verbindungsanforderung unterstützen. Der buf-Teil des WSABUF , auf den lpCallerId verweist, verweist auf einen sockaddr. Die sockaddr-Struktur wird entsprechend ihrer Adressfamilie interpretiert (in der Regel durch Umwandlung der Sockaddr in einen typspezifischen Typ für die Adressfamilie).

Der lpSQOS-Parameter verweist auf die FLOWSPEC-Strukturen für vom Aufrufer angegebene Sockets , eine für jede Richtung, gefolgt von zusätzlichen anbieterspezifischen Parametern. Die sendenden oder empfangenden Datenflussspezifikationswerte werden für alle unidirektionalen Sockets entsprechend ignoriert. Ein NULL-Wert gibt an, dass keine vom Aufrufer bereitgestellte Dienstqualität vorhanden ist und dass keine Aushandlung möglich ist. Ein lpSQOS-Zeiger ungleich NULL gibt an, dass eine Dienstqualitätsaushandlung erfolgen soll oder dass der Anbieter bereit ist, die Qualität der Dienstanforderung ohne Aushandlung zu akzeptieren.

Der lpGQOS-Parameter ist reserviert und sollte NULL sein. (reserviert für die zukünftige Verwendung mit Socketgruppen) verweist auf die FLOWSPEC-Struktur für die Socketgruppe, die der Aufrufer erstellen soll, eine für jede Richtung, gefolgt von zusätzlichen anbieterspezifischen Parametern. Ein NULL-Wert für lpGQOS gibt keine vom Aufrufer angegebene Dienstqualität der Gruppe an. Informationen zur Dienstqualität können zurückgegeben werden, wenn eine Aushandlung erfolgen soll.

Die lpCalleeId ist ein Parameter, der die lokale Adresse der verbundenen Entität enthält. Der buf-Teil des WSABUF, auf den von lpCalleeId verwiesen wird, verweist auf eine sockaddr-Struktur . Die sockaddr-Struktur wird entsprechend ihrer Adressfamilie interpretiert (in der Regel durch Umwandlung der Sockaddr in einen typspezifischen Typ für die Adressfamilie, z. B. struktur sockaddr_in).

LpCalleeData ist ein Ergebnisparameter, der von der Bedingungsfunktion verwendet wird, um Benutzerdaten an die Verbindungsentität zurückzuliefern. Das lpCalleeData-len> enthält zunächst die Länge des Puffers, der vom Dienstanbieter zugeordnet wird und auf den lpCalleeData-buf> verweist. Der Wert 0 (null) bedeutet, dass die Übergabe von Benutzerdaten an den Aufrufer nicht unterstützt wird. Die Bedingungsfunktion sollte bis zu lpCalleeData-len> Bytes der Daten in lpCalleeData-buf> kopieren und dann lpCalleeData-len> aktualisieren, um die tatsächliche Anzahl der übertragenen Bytes anzugeben. Wenn keine Benutzerdaten an den Aufrufer zurückgegeben werden sollen, sollte die Bedingungsfunktion lpCalleeData-len> auf Null festlegen. Das Format aller Adress- und Benutzerdaten ist spezifisch für die Adressfamilie, zu der der Socket gehört.

Der Parameter g wird innerhalb der Bedingungsfunktion zugewiesen, um eine der folgenden Aktionen anzugeben:

  • Wenn g ein vorhandener Socketgruppenbezeichner ist, fügen Sie dieser Gruppe s hinzu, sofern alle von dieser Gruppe festgelegten Anforderungen erfüllt sind.
  • Wenn g = SG_UNCONSTRAINED_GROUP, erstellen Sie eine uneingeschränkte Socketgruppe, und verwenden Sie s als erstes Mitglied.
  • Wenn g = SG_CONSTRAINED_GROUP, erstellen Sie eine eingeschränkte Socketgruppe, und verwenden Sie s als erstes Mitglied.
  • Wenn g = null ist, wird kein Gruppenvorgang ausgeführt.
Bei nicht eingeschränkten Gruppen können alle Sockets gruppiert werden, solange sie von einem einzelnen Dienstanbieter unterstützt werden. Eine eingeschränkte Socketgruppe kann nur aus verbindungsorientierten Sockets bestehen und erfordert, dass Verbindungen auf allen gruppierten Sockets mit derselben Adresse auf demselben Host erfolgen. Für neu erstellte Socketgruppen kann der neue Gruppenbezeichner mithilfe der getockopt-Funktion abgerufen werden, wobei der Levelparameter auf SOL_SOCKET und der optname-Parameter auf SO_GROUP_ID festgelegt ist. Eine Socketgruppe und die zugehörige Socketgruppen-ID bleiben gültig, bis der letzte Socket, der zu dieser Socketgruppe gehört, geschlossen wird. Socketgruppen-IDs sind für alle Prozesse für einen bestimmten Dienstanbieter eindeutig. Eine Socketgruppe und der zugehörige Bezeichner bleiben gültig, bis der letzte Socket, der zu dieser Socketgruppe gehört, geschlossen wird. Socketgruppenbezeichner sind für alle Prozesse für einen bestimmten Dienstanbieter eindeutig. Weitere Informationen zu Socketgruppen finden Sie in den Hinweisen zu den WSASocket-Funktionen .

Der dwCallbackData-Parameterwert , der an die Bedingungsfunktion übergeben wird, ist der Wert, der als dwCallbackData-Parameter im ursprünglichen WSAAccept-Aufruf übergeben wird. Dieser Wert wird nur vom Windows Socket Version 2-Client interpretiert. Dadurch kann ein Client kontextbezogene Informationen vom WSAAccept-Aufrufstandort an die Bedingungsfunktion übergeben. Dadurch werden der Bedingungsfunktion auch alle zusätzlichen Informationen bereitgestellt, die erforderlich sind, um zu bestimmen, ob die Verbindung akzeptiert werden soll oder nicht. Eine typische Verwendung besteht darin, einen (entsprechend umgewandelten) Zeiger an eine Datenstruktur zu übergeben, die Verweise auf anwendungsdefinierte Objekte enthält, denen dieser Socket zugeordnet ist.

Hinweis Um die Verwendung der WSAAccept-Funktion vor SYN-Angriffen zu schützen, müssen Anwendungen vollständige TCP-Handshakes (SYN-SYNACK-ACK) ausführen, bevor die Verbindungsanforderung gemeldet wird. Der Schutz vor SYN-Angriffen auf diese Weise führt dazu, dass die SO_CONDITIONAL_ACCEPT Socketoption nicht mehr funktioniert; Die bedingte Funktion wird weiterhin aufgerufen, und die WSAAccept-Funktion funktioniert ordnungsgemäß, aber Serveranwendungen, die darauf angewiesen sind, dass Clients den Handshake nicht ausführen können, funktionieren nicht ordnungsgemäß.
 
Hinweis Wenn Sie einen blockierenden Winsock-Aufruf wie WSAAccept ausstellen, muss Winsock möglicherweise auf ein Netzwerkereignis warten, bevor der Anruf abgeschlossen werden kann. Winsock führt in dieser Situation eine warnbare Wartezeit aus, die durch einen asynchronen Prozeduraufruf (APC) unterbrochen werden kann, der für denselben Thread geplant ist. Das Ausstellen eines weiteren blockierenden Winsock-Aufrufs innerhalb eines APC, der einen fortlaufend blockierenden Winsock-Aufruf im selben Thread unterbrochen hat, führt zu undefiniertem Verhalten und darf niemals von Winsock-Clients versucht werden.
 

Beispielcode

Im folgenden Beispiel wird die Verwendung der WSAAccept-Funktion veranschaulicht.
#include <winsock2.h>
#include <stdio.h>
#include <windows.h>

/* Define an example conditional function that depends on the pQos field */
int CALLBACK ConditionAcceptFunc(
    LPWSABUF lpCallerId,
    LPWSABUF lpCallerData,
    LPQOS pQos,
    LPQOS lpGQOS,
    LPWSABUF lpCalleeId,
    LPWSABUF lpCalleeData,
    GROUP FAR * g,
    DWORD_PTR dwCallbackData
    )
{

    if (pQos != NULL) {
        RtlZeroMemory(pQos, sizeof(QOS));
        return CF_ACCEPT;
    } else
        return CF_REJECT;
}

int main() {

    /* Declare and initialize variables */
    WSADATA wsaData;
    SOCKET ListenSocket, AcceptSocket;
    struct sockaddr_in saClient;
    int iClientSize = sizeof(saClient);
    u_short port = 27015;
    char* ip;
    sockaddr_in service;
    int error;

    /* Initialize Winsock */
    error = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (error) {
        printf("WSAStartup() failed with error: %d\n", error);
        return 1;
    }

    /* Create a TCP listening socket */
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {  
        printf("socket() failed with error: %d\n", WSAGetLastError() );
        WSACleanup();
        return 1;
    }

    /*-----------------------------------------  
     *  Set up the sock addr structure that the listening socket
     *  will be bound to. In this case, the structure holds the
     * local IP address and the port specified. */
    service.sin_family = AF_INET;
    service.sin_port = htons(port);
    hostent* thisHost;
    thisHost = gethostbyname("");
    ip = inet_ntoa (*(struct in_addr *)*thisHost->h_addr_list);
    service.sin_addr.s_addr = inet_addr(ip);

    /*-----------------------------------------
     *  Bind the listening socket to the IP address.
     * and port number specified by the sockaddr structure. */
    error = bind(ListenSocket, (SOCKADDR *) &service, sizeof(SOCKADDR));
    if (error == SOCKET_ERROR) {  
        printf("bind() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
  
    /* Make the socket listen for incoming connection requests */
    error = listen(ListenSocket, 1);
    if (error == SOCKET_ERROR) {  
        printf("listen() failed with error: %d\n", WSAGetLastError() );
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    printf("Listening...\n");
  
    /*-----------------------------------------
     *  Accept an incoming connection request on the
     *  listening socket and transfer control to the 
     * accepting socket. */
    AcceptSocket = WSAAccept(ListenSocket, (SOCKADDR*) &saClient, &iClientSize, 
        &ConditionAcceptFunc, NULL);
 
    /*  Now do some work with the AcceptSocket 
     *  At this point, the application could
     *  handle data transfer on the socket, or other socket
     * functionality.*/
    
    /* Then clean up and quit */

    closesocket(AcceptSocket);
    closesocket(ListenSocket);
    WSACleanup();

    return 0;
}

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

WSAConnect

WSASocket

Winsock-Funktionen

Winsock-Referenz

Akzeptieren

bind

connect

getsockopt

listen

select

sockaddr

Socket