Функция WSAAccept (winsock2.h)

Функция WSAAccept условно принимает подключение на основе возвращаемого значения функции условия, обеспечивает качество спецификаций потока обслуживания и позволяет передавать данные подключения.

Синтаксис

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

Параметры

[in] s

Дескриптор, определяющий сокет, прослушивающий подключения после вызова функции прослушивания.

[out] addr

Необязательный указатель на структуру sockaddr, которая получает адрес подключаемой сущности, как известно для уровня связи. Точный формат параметра надстройки определяется семейством адресов, установленным при создании сокета.

[in, out] addrlen

Необязательный указатель на целое число, содержащее длину sockaddr структуру, указываемую параметром надстройки в байтах.

[in] lpfnCondition

Адрес необязательной функции условия, указанной приложением, которая будет принимать или отклонять решение на основе информации вызывающего объекта, переданной в качестве параметров, и при необходимости создайте или присоедините группу сокетов, назначив соответствующее значение параметру результата g этой функции. Если этот параметр null, функция условия не вызывается.

[in] dwCallbackData

Данные обратного вызова, передаваемые в функцию условия, указанной приложением, в качестве значения параметра dwCallbackData, переданного функции условия. Этот параметр применим только в том случае, если параметр lpfnCondition не NULL. Этот параметр не интерпретируется сокетами Windows.

Возвращаемое значение

Если ошибка не возникает, WSAAccept возвращает значение типа SOCKET, которое является дескриптором для принятого сокета. В противном случае возвращается значение INVALID_SOCKET, а определенный код ошибки можно получить путем вызова WSAGetLastError.

Целое число, на которое ссылается addrlen изначально содержится пространство, на которое указывает надстройки. При возврате он будет содержать фактическую длину в байтах возвращаемого адреса.

Код ошибки Значение
WSAEACCES
Предпринята попытка получить доступ к сокету путем, запрещенному его разрешениями на доступ. Эта ошибка возвращается, если предлагаемый запрос подключения истек или был снят.
WSAECONNREFUSED
Подключение не может быть сделано, так как целевой компьютер активно отказался от него. Эта ошибка возвращается, если запрос на подключение был принудительно отклонен, как указано в возвращаемом значении функции условия (CF_REJECT).
WSAECONNRESET
Существующее подключение было принудительно закрыто удаленным узлом. Эта ошибка возвращается из входящего подключения, но впоследствии была завершена удаленным одноранговым узлом до принятия вызова.
WSAEFAULT
Система обнаружила недопустимый адрес указателя при попытке использовать аргумент указателя в вызове. Эта ошибка возвращается из параметра addrlen слишком мал или надстройки или lpfnCondition не входит в адресное пространство пользователя.
WSAEINTR
Блокировка была прервана вызовом WSACancelBlockingCall. Эта ошибка возвращается, если блокировка вызова сокетов Windows 1.1 была отменена через WSACancelBlockingCall.
WSAEINPROGRESS
В настоящее время выполняется операция блокировки. Эта ошибка возвращается, если выполняется блокировка вызова сокетов Windows 1.1.
WSAEINVAL
Указан недопустимый аргумент. Эта ошибка возвращается, если прослушивание не было вызвано до WSAAccept, возвращаемое значение функции условия не является допустимым или в любом случае, если указанный сокет находится в недопустимом состоянии.
WSAEMFILE
Слишком много открытых сокетов. Эта ошибка возвращается, если очередь не является простой при записи для WSAAccept и нет дескрипторов сокетов.
WSAENETDOWN
Операция сокета столкнулась с мертвой сетью. Эта ошибка возвращается, если сетевая подсистема завершилась ошибкой.
WSAENOBUFS
Не удалось выполнить операцию сокета, так как в системе недостаточно буферного пространства или из-за того, что очередь была заполнена. Эта ошибка возвращается, если буферное пространство недоступно.
WSAENOTSOCK
Операция была предпринята на то, что не является сокетом. Эта ошибка возвращается, если дескриптор сокета, переданный в параметре , не является сокетом.
WSAEOPNOTSUPP
Семейство протоколов не настроено в системе или отсутствует реализация для нее. Эта ошибка возвращается, если указанный сокет не является типом, поддерживающим службу, ориентированную на подключение.
WSAEWOULDBLOCK
Неблокирующая операция сокета не может быть завершена немедленно. Эта ошибка возвращается, если сокет помечается как неблокировка и не будут приниматься подключения.
WSANOTINITIALISED
Либо приложение не вызывает WSAStartup, либо WSAStartup. Эта ошибка возвращает успешный вызов функции WSAStartup не возникает перед использованием этой функции.
WSATRY_AGAIN
Обычно это временная ошибка во время разрешения имен узла и означает, что локальный сервер не получил ответ от авторитетного сервера. Эта ошибка возвращается, если принятие запроса подключения было отложено, как указано в возвращаемом значении функции условия (CF_DEFER).

Замечания

Функция WSAAccept извлекает первое подключение в очереди ожидающих подключений всокета сокета и проверяет его на соответствие функции условия, если указана функция условия (т. е. не NULL). Если функция условия возвращает CF_ACCEPT, WSAAccept создает новый сокет. Только что созданный сокет имеет те же свойства, что и сокетов , включая асинхронные события, зарегистрированные в WSAAsyncSelect или с WSAEventSelect. Если функция условия возвращает CF_REJECT, WSAAccept отклоняет запрос на подключение. Функция условия выполняется в том же потоке, что и эта функция, и должна вернуться как можно скорее. Если решение не может быть принято немедленно, функция условия должна вернуть CF_DEFER, чтобы указать, что решение не было принято, и никаких действий об этом запросе на подключение не должно приниматься поставщиком услуг. Когда приложение готово принять меры по запросу подключения, он вызовет WSAAccept снова и возвращает CF_ACCEPT или CF_REJECT в качестве возвращаемого значения из функции условия.

Сокет в режиме по умолчанию (блокировка) блокируется до тех пор, пока подключение не появится, когда приложение вызывает WSAAccept, и в очереди нет ожидающих подключений.

Сокет в режиме неблокировки (блокировка) завершается ошибкой WSAEWOULDBLOCK при вызове приложения WSAAccept и отсутствие подключений в очереди. После того как WSAAccept успешно и возвращает новый дескриптор сокета, приемленный сокет нельзя использовать для принятия дополнительных подключений. Исходный сокет остается открытым и прослушивает новые запросы на подключение.

Параметр надстройки является параметром результата, который заполняется адресом подключающейся сущности, как известно для уровня связи. Точный формат параметра надстройки определяется семейством адресов, в котором происходит взаимодействие. addrlen является параметром результата значений; Изначально он должен содержать объем пространства, на который указывает надстройка. При возврате он будет содержать фактическую длину (в байтах) возвращаемого адреса. Этот вызов используется с типами сокетов, ориентированными на подключение, например SOCK_STREAM. Если надстройки и/или addrlen равны NULL, то нет сведений о удаленном адресе принятого сокета. В противном случае эти два параметра будут заполнены, если подключение успешно принято.

Прототип функции условия определен в файле заголовка Winsock2.h как LPCONDITIONPROC, как показано ниже.

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 является заполнителем для функции обратного вызова, указанной приложением. Фактическая функция условия должна находиться в модуле DLL или приложения. Он экспортируется в файл определения модуля.

Параметр lpCallerId указывает на структуру WSABUF, содержащую адрес подключающейся сущности, где его параметр len — длина буфера в байтах, а его параметр buf является указателем на буфер. lpCallerData — это параметр значения, содержащий любые пользовательские данные. Сведения в этих параметрах отправляются вместе с запросом на подключение. Если нет доступных данных идентификации вызывающего или вызывающего абонента, соответствующие параметры будут null. Многие сетевые протоколы не поддерживают данные абонента во время подключения. Большинство обычных сетевых протоколов могут поддерживать сведения об идентификаторе вызывающего абонента во время запроса подключения. Часть WSABUF указывает на lpCallerId указывает на sockaddr. Структура sockaddr интерпретируется в соответствии с его семейством адресов (как правило, путем приведения sockaddr к определенному типу, конкретному семейству адресов).

Параметр lpSQOS ссылается на структуры FLOWSPEC для со кетов, указанных вызывающим оператором, по одному для каждого направления, а затем любые дополнительные параметры, относящиеся к поставщику. Значения спецификации отправки или получения потоков будут игнорироваться в соответствии с любыми однонаправленными сокетами. Значение NULL указывает, что качество обслуживания, предоставленное вызывающим абонентом, и что никаких переговоров невозможно. Указатель, отличный отNULL,lpSQOS указывает, что необходимо выполнить согласование качества обслуживания или что поставщик готов принять качество запроса на обслуживание без согласования.

Параметр lpGQOS зарезервирован и должен быть NULL. (зарезервировано для дальнейшего использования с группами сокетов) ссылается на структуру FLOWSPEC для группы сокетов, которую вызывающий объект создает, по одному для каждого направления, а затем все дополнительные параметры, относящиеся к поставщику. Значение NULL для lpGQOS указывает, что качество обслуживания указанной вызывающей группой не указано. Качество сведений об обслуживании может быть возвращено, если требуется согласование.

lpCalleeId — это параметр, содержащий локальный адрес подключенной сущности. буф части WSABUF, на которую указывает lpCalleeId указывает на структуру sockaddr. Структура sockaddr интерпретируется в соответствии со своей адресной семьей (как правило, путем приведения sockaddr к определенному типу, конкретному семейству адресов, например структуре sockaddr_in).

lpCalleeData — это параметр результата, используемый функцией условия для предоставления пользовательских данных обратно в сущность подключения. lpCalleeData->len изначально содержит длину буфера, выделенного поставщиком услуг, и указывает на lpCalleeData->buf. Значение нуля означает, что передача пользовательских данных обратно вызывающей стороне не поддерживается. Функция условия должна скопировать до lpCalleeData->len байт данных в lpCalleeData->buf, а затем обновить lpCalleeData->len, чтобы указать фактическое количество переданных байтов. Если пользовательские данные не передаются обратно вызывающей стороне, функция условия должна задать значение lpCalleeData->len равным нулю. Формат всех данных адреса и пользователя зависит от семейства адресов, к которому принадлежит сокет.

Параметр g назначается в функции условия, чтобы указать любое из следующих действий:

  • Если g является существующим идентификатором группы сокетов, добавьте в эту группу, если выполнены все требования, заданные этой группой.
  • Если g = SG_UNCONSTRAINED_GROUP, создайте группу без ограничений сокета и в качестве первого члена.
  • Если g = SG_CONSTRAINED_GROUP, создайте группу ограниченного сокета и в качестве первого члена.
  • Если g = ноль, операция группы не выполняется.
Для групп без ограничений любой набор сокетов можно сгруппировать до тех пор, пока они поддерживаются одним поставщиком услуг. Ограниченная группа сокетов может состоять только из сокетов, ориентированных на подключение, и требует, чтобы подключения ко всем сгруппированным сокетам были одинаковым адресом на одном узле. Для недавно созданных групп сокетов новый идентификатор группы можно получить с помощью функции getsockopt с параметром уровня для параметра SOL_SOCKET, а параметр optname иметь значение SO_GROUP_ID. Группа сокетов и идентификатор связанной группы сокетов остаются действительными до тех пор, пока последний сокет, принадлежащий этой группе сокетов, не будет закрыт. Идентификаторы групп сокетов уникальны во всех процессах для данного поставщика услуг. Группа сокетов и связанный идентификатор остаются действительными до тех пор, пока последний сокет, принадлежащий этой группе сокетов, не будет закрыт. Идентификаторы групп сокетов уникальны во всех процессах для данного поставщика услуг. Дополнительные сведения о группах сокетов см. в примечаниях для функций WSASocket.

Значение параметра dwCallbackData, переданное функции условия, является значением, переданным в качестве параметра dwCallbackData в исходном вызове WSAAccept. Это значение интерпретируется только клиентом Сокета Windows версии 2. Это позволяет клиенту передавать некоторые сведения о контексте из WSAAccept через функцию условия. Это также предоставляет функцию условия с дополнительными сведениями, необходимыми для определения того, следует ли принимать соединение или нет. Обычное использование заключается в передаче указателя (подходящего приведения) в структуру данных, содержащую ссылки на определяемые приложением объекты, с которым связан этот сокет.

Примечание Для защиты использования функции WSAAccept от атак SYN приложения должны выполнять полные подтверждения TCP (SYN-SYNACK-ACK) перед отправкой отчета о запросе на подключение. Защита от атак SYN таким образом приводит к тому, что параметр сокета SO_CONDITIONAL_ACCEPT становится неработоспособным; Условный вызов функции по-прежнему вызывается, и функция WSAAccept работает правильно, но серверные приложения, которые полагаются на клиентов, которые не могут выполнять подтверждение, не будут работать должным образом.
 
Примечание При выполнении блокирующего вызова Winsock, например WSAAccept, Winsock может потребоваться ждать сетевого события до завершения вызова. Winsock выполняет оповещенное ожидание в этой ситуации, которое может быть прервано асинхронным вызовом процедуры (APC), запланированным в одном потоке. Выдача другого блокирующего вызова Winsock внутри APC, который прервал текущий блокирующий вызов Winsock в том же потоке приведет к неопределенному поведению и никогда не должен пытаться клиентами Winsock.
 

пример кода

В следующем примере показано использование функции WSAAccept.
#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: эта функция поддерживается для приложений Магазина Windows Phone в Windows Phone 8 и более поздних версиях.

Windows 8.1 и Windows Server 2012 R2: эта функция поддерживается для приложений Магазина Windows в Windows 8.1, Windows Server 2012 R2 и более поздних версий.

Требования

Требование Ценность
минимальные поддерживаемые клиентские Windows 8.1, Windows Vista [классические приложения | Приложения UWP]
минимальный поддерживаемый сервер Windows Server 2003 [классические приложения | Приложения UWP]
целевая платформа Виндоус
заголовка winsock2.h
библиотеки Ws2_32.lib
DLL Ws2_32.dll

См. также

WSAAsyncSelect

WSAConnect

WSASocket

Функции Winsock

Справочник Winsock

принять

привязка

подключение

getsockopt

прослушивание

выбрать

sockaddr

сокета