Freigeben über


AcceptEx-Funktion (mswsock.h)

Die AcceptEx-Funktion akzeptiert eine neue Verbindung, gibt die lokale und Remoteadresse zurück und empfängt den ersten Datenblock, der von der Clientanwendung gesendet wird.

Hinweis Diese Funktion ist eine Microsoft-spezifische Erweiterung der Windows Sockets-Spezifikation.

 

Syntax

BOOL AcceptEx(
  [in]  SOCKET       sListenSocket,
  [in]  SOCKET       sAcceptSocket,
  [in]  PVOID        lpOutputBuffer,
  [in]  DWORD        dwReceiveDataLength,
  [in]  DWORD        dwLocalAddressLength,
  [in]  DWORD        dwRemoteAddressLength,
  [out] LPDWORD      lpdwBytesReceived,
  [in]  LPOVERLAPPED lpOverlapped
);

Parameter

[in] sListenSocket

Ein Deskriptor, der einen Socket identifiziert, der bereits mit der Listenfunktion aufgerufen wurde. Eine Serveranwendung wartet auf Versuche, eine Verbindung mit diesem Socket herzustellen.

[in] sAcceptSocket

Ein Deskriptor, der einen Socket identifiziert, für den eine eingehende Verbindung akzeptiert werden soll. Dieser Socket darf nicht gebunden oder verbunden sein.

[in] lpOutputBuffer

Ein Zeiger auf einen Puffer, der den ersten Datenblock empfängt, der für eine neue Verbindung gesendet wird, die lokale Adresse des Servers und die Remoteadresse des Clients. Die Empfangsdaten werden ab Offset 0 in den ersten Teil des Puffers geschrieben, während die Adressen in den zweiten Teil des Puffers geschrieben werden. Dieser Parameter muss angegeben werden.

[in] dwReceiveDataLength

Die Anzahl der Bytes in lpOutputBuffer , die am Anfang des Puffers für tatsächliche Empfangsdaten verwendet werden. Diese Größe sollte weder die Größe der lokalen Adresse des Servers noch die Remoteadresse des Clients enthalten. sie werden an den Ausgabepuffer angefügt. Wenn dwReceiveDataLength null ist, führt die Annahme der Verbindung nicht zu einem Empfangsvorgang. Stattdessen wird AcceptEx abgeschlossen, sobald eine Verbindung eingeht, ohne auf Daten zu warten.

[in] dwLocalAddressLength

Die Anzahl von Bytes, die für die lokalen Adressinformationen reserviert sind. Dieser Wert muss mindestens 16 Byte größer als die maximale Adresslänge für das verwendete Transportprotokoll sein.

[in] dwRemoteAddressLength

Die Anzahl der für die Remoteadresseninformationen reservierten Bytes. Dieser Wert muss mindestens 16 Byte größer als die maximale Adresslänge für das verwendete Transportprotokoll sein. Darf nicht null sein.

[out] lpdwBytesReceived

Ein Zeiger auf ein DWORD , das die Anzahl der empfangenen Bytes empfängt. Dieser Parameter wird nur festgelegt, wenn der Vorgang synchron abgeschlossen wird. Wenn sie ERROR_IO_PENDING zurückgibt und später abgeschlossen wird, wird dieses DWORD nie festgelegt, und Sie müssen die Anzahl der vom Vervollständigungsbenachrichtigungsmechanismus gelesenen Bytes abrufen.

[in] lpOverlapped

Eine OVERLAPPED-Struktur , die zum Verarbeiten der Anforderung verwendet wird. Dieser Parameter muss angegeben werden. Es darf nicht NULL sein.

Rückgabewert

Wenn kein Fehler auftritt, wurde die AcceptEx-Funktion erfolgreich abgeschlossen, und der Wert TRUE wird zurückgegeben.

Wenn die Funktion fehlschlägt, gibt AcceptExFALSE zurück. Die WSAGetLastError-Funktion kann dann aufgerufen werden, um erweiterte Fehlerinformationen zurückzugeben. Wenn WSAGetLastErrorERROR_IO_PENDING zurückgibt, wurde der Vorgang erfolgreich initiiert und wird noch ausgeführt. Wenn der Fehler WSAECONNRESET lautet, wurde eine eingehende Verbindung angezeigt, die jedoch vor annahme des Anrufs vom Remotepeer beendet wurde.

Hinweise

Die AcceptEx-Funktion kombiniert mehrere Socketfunktionen in einem einzelnen API-/Kernelübergang. Die AcceptEx-Funktion führt bei erfolgreicher Ausführung drei Aufgaben aus:

  • Eine neue Verbindung wird akzeptiert.
  • Sowohl die lokale Adresse als auch die Remoteadresse für die Verbindung werden zurückgegeben.
  • Der erste Datenblock, der vom Remotecomputer gesendet wird, wird empfangen.
Hinweis Der Funktionszeiger für die AcceptEx-Funktion muss zur Laufzeit abgerufen werden, indem die WSAIoctl-Funktion mit dem angegebenen SIO_GET_EXTENSION_FUNCTION_POINTER Opcode aufgerufen wird. Der an die WSAIoctl-Funktion übergebene Eingabepuffer muss WSAID_ACCEPTEX enthalten, einen GUID (Globally Unique Identifier), dessen Wert die AcceptEx-Erweiterungsfunktion identifiziert. Bei Erfolg enthält die von der WSAIoctl-Funktion zurückgegebene Ausgabe einen Zeiger auf die AcceptEx-Funktion . Die WSAID_ACCEPTEX GUID ist in der Headerdatei Mswsock.h definiert.
 

Ein Programm kann eine Verbindung mit einem Socket schneller herstellen, indem AcceptEx anstelle der Accept-Funktion verwendet wird.

Ein einzelner Ausgabepuffer empfängt die Daten, die lokale Socketadresse (der Server) und die Remotesocketadresse (der Client).

Die Verwendung eines einzelnen Puffers verbessert die Leistung. Bei Verwendung von AcceptEx muss die GetAcceptExSockaddrs-Funktion aufgerufen werden, um den Puffer in seine drei verschiedenen Teile (Daten, lokale Socketadresse und Remotesocketadresse) zu analysieren. Wenn die AcceptEx-Funktion unter Windows XP und höher abgeschlossen ist und die Option SO_UPDATE_ACCEPT_CONTEXT für den akzeptierten Socket festgelegt ist, kann die lokale Adresse, die dem akzeptierten Socket zugeordnet ist, auch mithilfe der getockname-Funktion abgerufen werden. Ebenso kann die Remoteadresse, die dem akzeptierten Socket zugeordnet ist, mithilfe der getpeername-Funktion abgerufen werden.

Die Puffergröße für die lokale adresse und die Remoteadresse muss 16 Byte größer sein als die Größe der sockaddr-Struktur für das verwendete Transportprotokoll, da die Adressen in einem internen Format geschrieben werden. Beispielsweise beträgt die Größe eines sockaddr_in (die Adressstruktur für TCP/IP) 16 Byte. Daher muss eine Puffergröße von mindestens 32 Bytes für die lokalen und Remoteadressen angegeben werden.

Die AcceptEx-Funktion verwendet im Gegensatz zur Accept-Funktion überlappende E/A. Wenn Ihre Anwendung AcceptEx verwendet, kann sie eine große Anzahl von Clients mit einer relativ kleinen Anzahl von Threads bedienen. Wie bei allen überlappenden Windows-Funktionen können entweder Windows-Ereignisse oder Abschlussports als Vervollständigungsbenachrichtigungsmechanismus verwendet werden.

Ein weiterer wichtiger Unterschied zwischen der AcceptEx-Funktion und der Accept-Funktion besteht darin, dass acceptEx erfordert, dass der Aufrufer bereits über zwei Sockets verfügt:

  • Eine , die den Socket angibt, an dem lauscht werden soll.
  • Eine , die den Socket angibt, für den die Verbindung akzeptiert werden soll.

Der sAcceptSocket-Parameter muss ein geöffneter Socket sein, der weder gebunden noch verbunden ist.

Der lpNumberOfBytesTransferred-Parameter der GetQueuedCompletionStatus-Funktion oder die GetOverlappedResult-Funktion gibt die Anzahl der in der Anforderung empfangenen Bytes an.

Wenn dieser Vorgang erfolgreich abgeschlossen wurde, kann sAcceptSocket übergeben werden, aber nur an die folgenden Funktionen:

ReadFile
WriteFile
send
WSASend
Recv
WSARecv
Transmitfile
closesocket
setsockopt(nur für SO_UPDATE_ACCEPT_CONTEXT)
Hinweis Wenn die TransmitFile-Funktion sowohl mit dem TF_DISCONNECT- als auch mit TF_REUSE_SOCKET-Flags aufgerufen wird, wurde der angegebene Socket in einen Zustand zurückgegeben, in dem er weder gebunden noch verbunden ist. Das Sockethandle kann dann an die AcceptEx-Funktion im sAcceptSocket-Parameter übergeben werden, aber der Socket kann nicht an die ConnectEx-Funktion übergeben werden.
 

Wenn die AcceptEx-Funktion zurückgegeben wird, befindet sich der Socket sAcceptSocket im Standardzustand für einen verbundenen Socket. Der Socket sAcceptSocket erbt die Eigenschaften des Sockets, der dem sListenSocket-Parameter zugeordnet ist, erst, wenn SO_UPDATE_ACCEPT_CONTEXT für den Socket festgelegt ist. Verwenden Sie die setockopt-Funktion , um die Option SO_UPDATE_ACCEPT_CONTEXT festzulegen, indem Sie sAcceptSocket als Sockethandle und sListenSocket als Optionswert angeben.

Beispiel:

//Need to #include <mswsock.h> for SO_UPDATE_ACCEPT_CONTEXT

int iResult = 0;

iResult =  setsockopt( sAcceptSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, 
    (char *)&sListenSocket, sizeof(sListenSocket) );
   

Wenn ein Empfangspuffer bereitgestellt wird, wird der überlappende Vorgang erst abgeschlossen, wenn eine Verbindung akzeptiert und Daten gelesen werden. Verwenden Sie die getockopt-Funktion mit der Option SO_CONNECT_TIME, um zu überprüfen, ob eine Verbindung akzeptiert wurde. Wenn sie akzeptiert wurde, können Sie bestimmen, wie lange die Verbindung hergestellt wurde. Der Rückgabewert ist die Anzahl der Sekunden, für die der Socket verbunden wurde. Wenn der Socket nicht verbunden ist, gibt der getsockopt 0xFFFFFFFF zurück. Anwendungen, die überprüfen, ob der überlappende Vorgang in Kombination mit der Option SO_CONNECT_TIME abgeschlossen wurde, können feststellen, dass eine Verbindung akzeptiert wurde, aber keine Daten empfangen wurden. Durch die Überprüfung einer Verbindung auf diese Weise kann eine Anwendung ermitteln, ob verbindungen, die für eine Weile eingerichtet wurden, keine Daten empfangen haben. Es wird empfohlen, solche Verbindungen durch Schließen des akzeptierten Sockets zu beenden, wodurch erzwingt, dass der AcceptEx-Funktionsaufruf mit einem Fehler abgeschlossen wird.

Beispiel:


INT seconds;
INT bytes = sizeof(seconds);
int iResult = 0;

iResult = getsockopt( sAcceptSocket, SOL_SOCKET, SO_CONNECT_TIME,
                      (char *)&seconds, (PINT)&bytes );

if ( iResult != NO_ERROR ) {
    printf( "getsockopt(SO_CONNECT_TIME) failed: %u\n", WSAGetLastError( ) );
    exit(1);
}

Hinweis Alle von einem bestimmten Thread initiierten E/A-Vorgänge werden abgebrochen, wenn dieser Thread beendet wird. Bei überlappenden Sockets können ausstehende asynchrone Vorgänge fehlschlagen, wenn der Thread geschlossen wird, bevor die Vorgänge abgeschlossen sind. Weitere Informationen finden Sie unter ExitThread .
 

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.

Beispielcode

Im folgenden Beispiel wird die AcceptEx-Funktion mit überlappenden E/A- und Abschlussports verwendet.
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
#include <stdio.h>

// Need to link with Ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int main()
{
    //----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult = 0;
    BOOL bRetVal = FALSE;

    HANDLE hCompPort;
    HANDLE hCompPort2;
    
    LPFN_ACCEPTEX lpfnAcceptEx = NULL;
    GUID GuidAcceptEx = WSAID_ACCEPTEX;
    WSAOVERLAPPED olOverlap;

    SOCKET ListenSocket = INVALID_SOCKET;
    SOCKET AcceptSocket = INVALID_SOCKET;
    sockaddr_in service;
    char lpOutputBuf[1024];
    int outBufLen = 1024;
    DWORD dwBytes;

    hostent *thisHost;
    char *ip;
    u_short port;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != NO_ERROR) {
        wprintf(L"Error at WSAStartup\n");
        return 1;
    }    

    // Create a handle for the completion port
    hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (u_long) 0, 0);
    if (hCompPort == NULL) {
        wprintf(L"CreateIoCompletionPort failed with error: %u\n",
            GetLastError() );
        WSACleanup();
        return 1;
    }
            
    // Create a listening socket
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"Create of ListenSocket socket failed with error: %u\n",
            WSAGetLastError() );
        WSACleanup();
        return 1;
    }

    // Associate the listening socket with the completion port
    CreateIoCompletionPort((HANDLE) ListenSocket, hCompPort, (u_long) 0, 0);

    //----------------------------------------
    // Bind the listening socket to the local IP address
    // and port 27015
    port = 27015;
    thisHost = gethostbyname("");
    ip = inet_ntoa(*(struct in_addr *) *thisHost->h_addr_list);

    service.sin_family = AF_INET;
    service.sin_addr.s_addr = inet_addr(ip);
    service.sin_port = htons(port);

    if (bind(ListenSocket, (SOCKADDR *) & service, sizeof (service)) == SOCKET_ERROR) {
        wprintf(L"bind failed with error: %u\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    //----------------------------------------
    // Start listening on the listening socket
    iResult = listen(ListenSocket, 100);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"listen failed with error: %u\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    wprintf(L"Listening on address: %s:%d\n", ip, port);

    // Load the AcceptEx function into memory using WSAIoctl.
    // The WSAIoctl function is an extension of the ioctlsocket()
    // function that can use overlapped I/O. The function's 3rd
    // through 6th parameters are input and output buffers where
    // we pass the pointer to our AcceptEx function. This is used
    // so that we can call the AcceptEx function directly, rather
    // than refer to the Mswsock.lib library.
    iResult = WSAIoctl(ListenSocket, SIO_GET_EXTENSION_FUNCTION_POINTER,
             &GuidAcceptEx, sizeof (GuidAcceptEx), 
             &lpfnAcceptEx, sizeof (lpfnAcceptEx), 
             &dwBytes, NULL, NULL);
    if (iResult == SOCKET_ERROR) {
        wprintf(L"WSAIoctl failed with error: %u\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // Create an accepting socket
    AcceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (AcceptSocket == INVALID_SOCKET) {
        wprintf(L"Create accept socket failed with error: %u\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // Empty our overlapped structure and accept connections.
    memset(&olOverlap, 0, sizeof (olOverlap));

    bRetVal = lpfnAcceptEx(ListenSocket, AcceptSocket, lpOutputBuf,
                 outBufLen - ((sizeof (sockaddr_in) + 16) * 2),
                 sizeof (sockaddr_in) + 16, sizeof (sockaddr_in) + 16, 
                 &dwBytes, &olOverlap);
    if (bRetVal == FALSE) {
        wprintf(L"AcceptEx failed with error: %u\n", WSAGetLastError());
        closesocket(AcceptSocket);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // Associate the accept socket with the completion port
    hCompPort2 = CreateIoCompletionPort((HANDLE) AcceptSocket, hCompPort, (u_long) 0, 0); 
    // hCompPort2 should be hCompPort if this succeeds
    if (hCompPort2 == NULL) {
        wprintf(L"CreateIoCompletionPort associate failed with error: %u\n",
            GetLastError() );
        closesocket(AcceptSocket);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    
    // Continue on to use send, recv, TransmitFile(), etc.,.
    //...

    return 0;
}


Hinweise für QoS

Die TransmitFile-Funktion ermöglicht das Festlegen von zwei Flags, TF_DISCONNECT oder TF_REUSE_SOCKET, die den Socket nach der Übertragung der Datei in einen "getrennten, wiederverwendbaren" Zustand zurückversetzen. Diese Flags sollten nicht für einen Socket verwendet werden, bei dem die Dienstqualität angefordert wurde, da der Dienstanbieter jede Dienstqualität im Zusammenhang mit dem Socket sofort löschen kann, bevor die Dateiübertragung abgeschlossen ist. Der beste Ansatz für einen QoS-fähigen Socket besteht darin, einfach die Closesocket-Funktion aufzurufen, wenn die Dateiübertragung abgeschlossen ist, anstatt sich auf diese Flags zu verlassen.

Hinweise für ATM

Bei Verwendung des asynchronen Übertragungsmodus (ATM) mit Windows Sockets 2 gibt es wichtige Probleme im Zusammenhang mit der Verbindungseinrichtung. Wichtige Informationen zum Einrichten der ATM-Verbindung finden Sie im Abschnitt Hinweise in der Dokumentation zur Akzeptanzfunktion .

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 mswsock.h (include Mswsock.h)
Bibliothek Mswsock.lib
DLL Mswsock.dll

Weitere Informationen

GetAcceptExSockaddrs

GetOverlappedResult

GetQueuedCompletionStatus

OVERLAPPED

Transmitfile

Winsock-Funktionen

Winsock-Referenz

Akzeptieren

closesocket

getsockopt

listen

sockaddr