Share via


AcceptEx-Funktion (winsock.h)

Die AcceptEx-Funktion akzeptiert eine neue Verbindung, gibt die lokale adresse und die 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 Verbindungsversuche mit diesem Socket.

[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 null in den ersten Teil des Puffers geschrieben, während die Adressen in den letzten Teil des Puffers geschrieben werden. Dieser Parameter muss angegeben werden.

[in] dwReceiveDataLength

Die Anzahl der Bytes in lpOutputBuffer , die für tatsächliche Empfangsdaten am Anfang des Puffers 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 der für die lokalen Adressinformationen reservierten Bytes. Dieser Wert muss mindestens 16 Bytes mehr als die maximale Adresslänge für das verwendete Transportprotokoll betragen.

[in] dwRemoteAddressLength

Die Anzahl der für die Remoteadresseninformationen reservierten Bytes. Dieser Wert muss mindestens 16 Bytes mehr als die maximale Adresslänge für das verwendete Transportprotokoll betragen. Darf nicht 0 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 es ERROR_IO_PENDING zurückgibt und später abgeschlossen wird, wird diese 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 weiterhin ausgeführt. Wenn der Fehler WSAECONNRESET lautet, wurde eine eingehende Verbindung angezeigt, die anschließend vom Remotepeer beendet wurde, bevor der Anruf angenommen wurde.

Hinweise

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

  • Eine neue Verbindung wird akzeptiert.
  • Sowohl die lokale als auch die Remoteadresse für die Verbindung werden zurückgegeben.
  • Der erste Block von Daten, die von der Remotedaten gesendet werden, 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 global eindeutigen Bezeichner (GUID), 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 mithilfe von AcceptEx anstelle der Accept-Funktion schneller eine Verbindung mit einem Socket herstellen.

Ein einzelner Ausgabepuffer empfängt die Daten, die lokale Socketadresse (der Server) und die Remote-Socketadresse (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 Remotesocketsadresse) 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 dem akzeptierten Socket zugeordnete lokale Adresse 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 Bytes höher 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 Bytes. 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 Vervollständigungsports 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 offener Socket sein, der weder gebunden noch verbunden ist.

Der lpNumberOfBytesTransferred-Parameter der GetQueuedCompletionStatus-Funktion oder der 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 TF_REUSE_SOCKET-Flag aufgerufen wird, wurde der angegebene Socket in einen Zustand zurückgegeben, in dem er weder gebunden noch verbunden ist. Das Sockethandle kann dann im sAcceptSocket-Parameter an die AcceptEx-Funktion ü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 ein verbundenes Socket. Der Socket sAcceptSocket erbt erst dann die Eigenschaften des Sockets, der dem sListenSocket-Parameter zugeordnet ist, bis 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 von Sekunden, 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 eine Weile eingerichtet wurden, keine Daten empfangen haben. Es wird empfohlen, solche Verbindungen durch Schließen des akzeptierten Sockets zu beenden, wodurch 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 werden. Weitere Informationen finden Sie unter ExitThread .
 

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 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 Vervollständigungsports 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 in einen "getrennten, wiederverwendbaren" Zustand zurückgeben. Diese Flags sollten nicht für ein Socket verwendet werden, bei dem die Dienstqualität angefordert wurde, da der Dienstanbieter alle mit dem Socket verbundenen Dienstqualität 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 zur Einrichtung der ATM-Verbindung finden Sie im Abschnitt Hinweise in der Dokumentation zur Annahmefunktion .

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 winsock.h (Mswsock.h einschließen)
Bibliothek Mswsock.lib
DLL Mswsock.dll

Weitere Informationen

GetAcceptExSockaddrs

GetOverlappedResult

GetQueuedCompletionStatus

OVERLAPPED

Transmitfile

Winsock-Funktionen

Winsock-Referenz

Akzeptieren

closesocket

getsockopt

listen

sockaddr