Freigeben über


WSAAccept-Funktion (winsock2.h)

Die WSAAccept Funktion akzeptiert bedingt eine Verbindung basierend auf dem Rückgabewert einer Bedingungsfunktion, stellt qualitätsbezogene Dienstflussspezifikationen 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 auf der Kommunikationsebene bekannt. Das genaue Format des addr Parameter 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 Byte verweist.

[in] lpfnCondition

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

[in] dwCallbackData

Rückrufdaten, die an die anwendungsspezifische Bedingungsfunktion als Wert der an die Bedingungsfunktion übergebenen dwCallbackData Parameter übergeben werden. Dieser Parameter gilt nur, wenn der parameter lpfnCondition 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 ein Wert von INVALID_SOCKET zurückgegeben, und ein bestimmter Fehlercode kann durch Aufrufen WSAGetLastError-abgerufen werden.

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

Fehlercode Bedeutung
WSAEACCES
Es wurde versucht, auf ein Socket in einer Weise zuzugreifen, die durch seine Zugriffsberechtigungen verboten ist. Dieser Fehler wird zurückgegeben, wenn die angebotene Verbindungsanforderung timeout oder zurückgezogen wurde.
WSAECONNREFUSED
Es konnte keine Verbindung hergestellt werden, da der Zielcomputer sie aktiv abgelehnt hat. Dieser Fehler wird zurückgegeben, wenn die Verbindungsanforderung erzwungen abgelehnt wurde, wie im Rückgabewert der Bedingungsfunktion angegeben (CF_REJECT).
WSAECONNRESET-
Eine vorhandene Verbindung wurde vom Remotehost forcibly geschlossen. Dieser Fehler wird von einer eingehenden Verbindung zurückgegeben, wurde jedoch vor der Annahme des Anrufs vom Remote-Peer beendet.
WSAEFAULT-
Das System hat beim Versuch, ein Zeigerargument in einem Aufruf zu verwenden, eine ungültige Zeigeradresse erkannt. Dieser Fehler wird vom parameter addrlen zurückgegeben, oder der addr oder lpfnCondition ist nicht Teil des Benutzeradressraums.
WSAEINTR-
Ein Blockierungsvorgang wurde durch einen Aufruf von WSACancelBlockingCallunterbrochen. Dieser Fehler wird zurückgegeben, wenn ein blockierter Windows Sockets 1.1-Aufruf über WSACancelBlockingCall-abgebrochen wurde.
WSAEINPROGRESS-
Zurzeit wird ein Blockierungsvorgang ausgeführt. Dieser Fehler wird zurückgegeben, wenn ein blockierter Windows Sockets 1.1-Aufruf ausgeführt wird.
WSAEINVAL-
Es wurde ein ungültiges Argument angegeben. Dieser Fehler wird zurückgegeben, wenn Lauschen vor WSAAcceptnicht aufgerufen wurde, der Rückgabewert der Bedingungsfunktion kein gültiger Wert ist oder wenn sich der angegebene Socket in einem ungültigen Zustand befindet.
WSAEMFILE-
Zu viele offene Sockets. Dieser Fehler wird zurückgegeben, wenn die Warteschlange beim Eintrag in WSAAccept- nicht inAktiv ist und keine Socketdeskriptoren verfügbar sind.
WSAENETDOWN-
Bei einem Socketvorgang ist ein inaktives Netzwerk aufgetreten. Dieser Fehler wird zurückgegeben, wenn das Netzwerksubsystem fehlgeschlagen ist.
WSAENOBUFS
Ein Vorgang für einen Socket konnte nicht ausgeführt werden, da das System nicht genügend Pufferspeicher hat oder weil eine Warteschlange voll war. Dieser Fehler wird zurückgegeben, wenn kein Pufferspeicher verfügbar ist.
WSAENOTSOCK
Bei einem Vorgang wurde versucht, dass es sich nicht um einen Socket handelt. Dieser Fehler wird zurückgegeben, wenn der socketdeskriptor, der im s-Parameter übergeben wurde, kein Socket ist.
WSAEOPNOTSUPP
Die Protokollfamilie wurde nicht in das System konfiguriert, oder es ist keine Implementierung vorhanden. Dieser Fehler wird zurückgegeben, wenn der referenzierte Socket kein Typ ist, der den verbindungsorientierten Dienst unterstützt.
WSAEWOULDBLOCK
Ein nicht blockierenden Socketvorgang konnte nicht sofort abgeschlossen werden. Dieser Fehler wird zurückgegeben, wenn der Socket als nicht blockiert markiert ist und keine Verbindungen akzeptiert werden.
WSANOTINITIALISIERT
Entweder hat die Anwendung WSAStartup-nicht aufgerufen, oder WSAStartup fehlgeschlagen. Dieser Fehler wird von einem erfolgreichen Aufruf des WSAStartup- Funktions dit nicht vor der Verwendung dieser Funktion zurückgegeben.
WSATRY_AGAIN
Dies ist in der Regel ein temporärer Fehler bei der Hostnamenauflösung und bedeutet, dass der lokale Server keine Antwort von einem autorisierenden Server empfangen hat. Dieser Fehler wird zurückgegeben, wenn die Annahme der Verbindungsanforderung verzögert wurde, wie im Rückgabewert der Bedingungsfunktion angegeben (CF_DEFER).

Bemerkungen

Die WSAAccept-Funktion extrahiert die erste Verbindung in der Warteschlange ausstehender Verbindungen sund überprüft sie anhand der Bedingungsfunktion, vorausgesetzt, die Bedingungsfunktion wird angegeben (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 socket s einschließlich asynchroner Ereignisse, die mit WSAAsyncSelect- oder mit WSAEventSelect-registriert sind. Wenn die Bedingungsfunktion CF_REJECT zurückgibt, weist WSAAccept die Verbindungsanforderung zurück. Die Bedingungsfunktion wird im gleichen 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 keine Aktion zu dieser Verbindungsanforderung sollte vom Dienstanbieter getroffen werden. 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 (Blockieren) wird blockiert, bis eine Verbindung vorhanden ist, wenn eine Anwendung WSAAccept- aufruft und keine Verbindungen in der Warteschlange ausstehen.

Ein Socket im Nichtblockingmodus (Blockieren) schlägt mit dem Fehler WSAEWOULDBLOCK- fehl, wenn eine Anwendung WSAAccept aufruft und keine Verbindungen in der Warteschlange ausstehen. Nachdem WSAAccept erfolgreich und einen neuen Socketziehpunkt 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 gefüllt ist, die als Kommunikationsschicht bezeichnet wird. Das genaue Format des addr Parameter wird durch die Adressfamilie bestimmt, in der die Kommunikation erfolgt. Die addrlen ist ein Wertergebnisparameter; sie sollte zunächst den Abstand enthalten, auf den Addr-verweist. Bei der Rückgabe enthält sie die tatsächliche Länge (in Byte) der zurückgegebenen Adresse. Dieser Aufruf wird mit verbindungsorientierten Sockettypen wie SOCK_STREAM verwendet. Wenn addr und/oder addrlen gleich NULL-sind, werden keine Informationen zur Remoteadresse des akzeptierten Sockets zurückgegeben. Andernfalls werden diese beiden Parameter ausgefüllt, wenn die Verbindung erfolgreich akzeptiert wird.

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

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
);

Die 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 der Moduldefinitionsdatei exportiert.

Der lpCallerId Parameter verweist auf eine WSABUF-Struktur, die die Adresse der Verbindungsentität enthält, wobei der parameter len die Länge des Puffers in Byte darstellt und der buf Parameter ein Zeiger auf den Puffer ist. Die lpCallerData- ist ein Wertparameter, der alle Benutzerdaten enthält. Die Informationen in diesen Parametern werden zusammen mit der Verbindungsanforderung gesendet. Wenn keine Anruferidentifikations- oder Aufruferdaten verfügbar sind, werden die entsprechenden Parameter NULL. Viele Netzwerkprotokolle unterstützen keine Verbindungszeit-Anruferdaten. Die meisten herkömmlichen Netzwerkprotokolle können erwartet werden, dass Anruferbezeichnerinformationen zur Verbindungsanforderungszeit unterstützt werden. Der buf-Teil des WSABUF-, auf den lpCallerId verweist, verweist auf einen sockaddr-. Die sockaddr Struktur wird gemäß ihrer Adressfamilie interpretiert (in der Regel durch Umwandlung der sockaddr- in einen bestimmten Typ, der für die Adressfamilie spezifisch ist).

Der lpSQOS Parameter verweist auf die FLOWSPEC- Strukturen für Socket-s, die vom Aufrufer angegeben werden, eine für jede Richtung, gefolgt von zusätzlichen anbieterspezifischen Parametern. Die Sende- oder Empfangsflussspezifikationswerte werden für alle unidirektionalen Sockets entsprechend ignoriert. Ein NULL- Wert gibt an, dass keine vom Aufrufer bereitgestellte Servicequalität vorhanden ist und dass keine Aushandlung möglich ist. Ein nichtNULL-lpSQOS- Zeiger weist darauf hin, dass eine Dienstqualität auftritt oder der Anbieter bereit ist, die Qualität der Serviceanfrage 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 anruferspezifische Dienstqualität an. Qualitätsinformationen können zurückgegeben werden, wenn die 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 lpCalleeId verweist auf eine sockaddr- Struktur. Die sockaddr Struktur wird gemäß ihrer Adressfamilie interpretiert (in der Regel durch Umwandlung der sockaddr in einen bestimmten Typ, der für die Adressfamilie spezifisch ist, z. B. Struktur sockaddr_in).

Die lpCalleeData- ist ein Ergebnisparameter, der von der Bedingungsfunktion verwendet wird, um Benutzerdaten an die Verbindungsentität zurückzuliefern. Die lpCalleeData->len enthält zunächst die Länge des vom Dienstanbieter zugewiesenen Puffers und verweist auf lpCalleeData->buf. Ein Wert von Null bedeutet, dass benutzerdaten zurück an den Aufrufer übergeben werden, wird nicht unterstützt. Die Bedingungsfunktion sollte bis zu lpCalleeData->len Bytes von Daten in lpCalleeData->bufkopieren und dann lpCalleeData->len aktualisieren, um die tatsächliche Anzahl der übertragenen Bytes anzugeben. Wenn keine Benutzerdaten an den Aufrufer übergeben 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 in der Bedingungsfunktion zugewiesen, um eine der folgenden Aktionen anzugeben:

  • Wenn g ein vorhandener Socketgruppenbezeichner ist, fügen Sie dieser Gruppe hinzu, vorausgesetzt, alle von dieser Gruppe festgelegten Anforderungen sind erfüllt.
  • Wenn g = SG_UNCONSTRAINED_GROUP, erstellen Sie eine nicht eingeschränkte Socketgruppe und s als erstes Mitglied.
  • Wenn g = SG_CONSTRAINED_GROUP, erstellen Sie eine eingeschränkte Socketgruppe und als erstes Mitglied.
  • Wenn g = null, 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 dieselbe Adresse auf demselben Host aufweisen. Für neu erstellte Socketgruppen kann der neue Gruppenbezeichner mithilfe getsockopt- Funktion abgerufen werden, wobei Ebene Parameter auf SOL_SOCKET festgelegt ist und der optname Parameter auf SO_GROUP_IDfestgelegt ist. Eine Socketgruppe und die zugehörige Socketgruppen-ID bleiben gültig, bis der letzte Socket, der zu dieser Socketgruppe gehört, geschlossen ist. 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 Anmerkungen zu den WSASocket- Funktionen.

Der an die Bedingungsfunktion übergebene dwCallbackData Parameterwert 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 aus der WSAAccept Aufrufen der Website an die Bedingungsfunktion übergeben. Dadurch wird auch die Bedingungsfunktion mit allen zusätzlichen Informationen bereitgestellt, die erforderlich sind, um festzustellen, ob die Verbindung akzeptiert werden soll. Eine typische Verwendung besteht darin, einen (entsprechend umwandelnden) 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 führt dazu, dass die SO_CONDITIONAL_ACCEPT Socketoption inoperativ wird; die bedingte Funktion wird weiterhin aufgerufen, und die WSAAccept--Funktion funktioniert ordnungsgemäß, aber Serveranwendungen, die auf Clients angewiesen sind, die den Handshake nicht ausführen können, funktionieren nicht ordnungsgemäß.
 
Hinweis Beim Ausgeben eines blockierten Winsock-Anrufs wie WSAAccept-muss Winsock möglicherweise auf ein Netzwerkereignis warten, bevor der Anruf abgeschlossen werden kann. Winsock führt in dieser Situation eine warnbare Wartezeit durch, die durch einen asynchronen Prozeduraufruf (APC) unterbrochen werden kann, der im selben Thread geplant ist. Das Ausstellen eines weiteren blockierenden Winsock-Aufrufs innerhalb eines APC, der einen fortlaufend blockierten Winsock-Aufruf im selben Thread unterbrochen hat, führt zu nicht definiertem Verhalten und darf niemals von Winsock-Clients versucht werden.
 

Beispielcode

Im folgenden Beispiel wird die Verwendung der funktion WSAAccept 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 auf Windows Phone 8 und höher unterstützt.

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

Anforderungen

Anforderung Wert
mindestens unterstützte Client- Windows 8.1, Windows Vista [Desktop-Apps | UWP-Apps]
mindestens unterstützte Server- Windows Server 2003 [Desktop-Apps | UWP-Apps]
Zielplattform- Fenster
Header- winsock2.h
Library Ws2_32.lib
DLL- Ws2_32.dll

Siehe auch

WSAAsyncSelect-

WSAConnect-

WSASocket-

Winsock-Funktionen

Winsock Reference

akzeptieren

binden

verbinden

getsockopt

auswählen

sockaddr-

Socket-