Функция WSAEventSelect (winsock2.h)
Функция WSAEventSelect указывает объект события, связанный с указанным набором FD_XXX сетевых событий.
Синтаксис
int WSAAPI WSAEventSelect(
[in] SOCKET s,
[in] WSAEVENT hEventObject,
[in] long lNetworkEvents
);
Параметры
[in] s
Дескриптор, определяющий сокет.
[in] hEventObject
Дескриптор, определяющий объект события, связанный с указанным набором FD_XXX сетевых событий.
[in] lNetworkEvents
Битовая маска, указывающая сочетание FD_XXX сетевых событий, в которых заинтересовано приложение.
Возвращаемое значение
Возвращаемое значение равно нулю, если спецификация приложения сетевых событий и связанного объекта события была успешной. В противном случае возвращается значение SOCKET_ERROR, а определенный номер ошибки можно получить, вызвав WSAGetLastError.
Как и в случае с функциями select и WSAsyncSelect , WSAEventSelect часто используется для определения того, когда операция передачи данных (отправка или восстановление) может быть выполнена с ожиданием немедленного успеха. Тем не менее, надежное приложение должно быть готово к тому, что объект события задан и он выдает вызов Сокетов Windows, который немедленно возвращает WSAEWOULDBLOCK . Например, возможна следующая последовательность операций:
- Данные поступают в сокеты; Сокеты Windows задает объект события WSAEventSelect .
- Приложение выполняет некоторую другую обработку.
- Во время обработки приложение выдает ioctlsocket(s, FIONREAD...) и замечает, что есть данные, готовые для чтения.
- Приложение выдает recv(s,...) для чтения данных.
- В конечном итоге приложение ожидает объект события, указанный в WSAEventSelect, который возвращает немедленно, указывая, что данные готовы к чтению.
- Приложение выдает ошибку recv(s,...), которая завершается ошибкой WSAEWOULDBLOCK.
Сетевое событие | Повторное включение функции |
---|---|
|
Функция recv, recvfrom, WSARecv, WSARecvEx или WSARecvFrom . |
|
Функция send, sendto, WSASend или WSASendTo . |
|
Функция recv, recvfrom, WSARecv, WSARecvEx или WSARecvFrom . |
|
Функция accept, AcceptEx или WSAAccept , если возвращенный код ошибки не WSATRY_AGAIN, указывающий, что функция условия вернула CF_DEFER. |
|
Нет. |
|
Нет. |
|
Функция WSAIoctl с командой SIO_GET_QOS. |
|
Зарезервировано. |
|
Функция WSAIoctl с командой SIO_ROUTING_INTERFACE_CHANGE. |
|
Функция WSAIoctl с командой SIO_ADDRESS_LIST_CHANGE. |
Любой вызов процедуры повторного преобразования, даже если он завершается сбоем, приводит к повторной записи и сигнализации для соответствующего сетевого события и объекта события.
Для FD_READ, FD_OOB и FD_ACCEPT сетевых событий запись сетевых событий и сигнализация объекта события активируются на уровне. Это означает, что если вызывается подпрограмма повторного преобразования и соответствующее условие сети остается действительным после вызова, сетевое событие записывается и задается связанный объект события. Это позволяет приложению управлять событиями и не беспокоиться о объеме данных, поступающих в любой момент времени. Рассмотрим следующую последовательность:
- Поставщик транспорта получает 100 байт данных в сокетах и заставляет WS2_32.DLL записывать сетевое событие FD_READ и задавать связанный объект события.
- Приложение выдает recv(s, buffptr, 50, 0) для чтения 50 байт.
- Поставщик транспорта заставляет WS2_32.DLL записывать сетевое событие FD_READ и снова задает связанный объект события, так как данные еще не считываются.
Событие FD_QOS считается запущенным ребром. Сообщение будет опубликовано ровно один раз при изменении качества обслуживания. Дальнейшие сообщения не будут получаться, пока поставщик не обнаружит дальнейшее изменение качества обслуживания или приложение не пересматривает качество обслуживания для сокета.
События FD_ROUTING_INTERFACE_CHANGE и FD_ADDRESS_LIST_CHANGE также считаются активированными по краям. Сообщение будет опубликовано ровно один раз, когда произойдет изменение после запроса уведомления приложением путем выдачи WSAIoctl с SIO_ROUTING_INTERFACE_CHANGE или SIO_ADDRESS_LIST_CHANGE соответственно. Другие сообщения не будут приходить, пока приложение повторно не выдаст IOCTL и не будет обнаружено другое изменение после выдачи IOCTL.
Если сетевое событие уже произошло, когда приложение вызывает WSAEventSelect или вызывается функция reenabling, то сетевое событие записывается и соответствующий объект события задается соответствующим образом. Например, рассмотрим следующую последовательность:
- Приложение вызывает прослушивание.
- Запрос на подключение получен, но еще не принят.
- Приложение вызывает WSAEventSelect , указывая, что оно заинтересовано в сетевом событии FD_ACCEPT для сокета. Из-за сохраняемости сетевых событий Сокеты Windows записывают сетевое событие FD_ACCEPT и немедленно задает связанный объект события.
Сетевое событие FD_OOB используется только в том случае, если сокет настроен для получения данных OOB отдельно. Если сокет настроен для получения данных OOB в встроенном режиме, данные OOB (ускоряемые) обрабатываются как обычные данные, и приложение должно зарегистрировать интерес и получить FD_READ сетевое событие, а не сетевое событие FD_OOB. Приложение может задать или проверить способ обработки данных OOB с помощью метода setsockopt или getsockopt для параметра SO_OOBINLINE.
Код ошибки в сетевом событии FD_CLOSE указывает, было ли закрытие сокета корректно или прервано. Если код ошибки равен нулю, то закрытие было корректно; Если код ошибки — WSAECONNRESET, то виртуальный канал сокета был сброшен. Это относится только к сокетам, ориентированным на подключение, таким как SOCK_STREAM.
Сетевое событие FD_CLOSE записывается при получении указания закрытия для виртуального канала, соответствующего сокету. С точки зрения TCP это означает, что FD_CLOSE записывается, когда подключение переходит в состояния TIME WAIT или CLOSE WAIT. Это происходит из-за того, что удаленный конец выполняет завершение работы на стороне отправки или закрытие. FD_CLOSE публикации после считывания всех данных из сокета. Приложение должно проверка оставшихся данных после получения FD_CLOSE, чтобы избежать любой возможности потери данных. Дополнительные сведения см. в разделе Корректное завершение работы, параметры задержки и Закрытие сокета и функция завершения работы .
Обратите внимание, что сокеты Windows записывают только сетевое событие FD_CLOSE, указывающее на закрытие виртуального канала. Он не будет записывать сетевое событие FD_READ, чтобы указать это условие.
Сетевое событие FD_QOS или FD_GROUP_QOS записывается при любом параметре в спецификации потока, связанном с сокетами. Приложения должны использовать WSAIoctl с командой SIO_GET_QOS, чтобы получить текущее качество обслуживания для сокетов.
Сетевое событие FD_ROUTING_INTERFACE_CHANGE записывается, когда локальный интерфейс, который должен использоваться для достижения назначения, указанного в WSAIoctl , с SIO_ROUTING_INTERFACE_CHANGE изменениями после выдачи такого IOCTL.
Сетевое событие FD_ADDRESS_LIST_CHANGE записывается, когда список адресов семейства протоколов для сокета, к которому приложение может привязаться, изменяется после выдачи WSAIoctl с SIO_ADDRESS_LIST_CHANGE .
Код ошибки | Значение |
---|---|
WSANOTINITIALISED | Перед использованием этой функции должен быть выполнен успешный вызов WSAStartup . |
WSAENETDOWN | Произошел сбой сетевой подсистемы. |
WSAEINVAL | Один из указанных параметров является недопустимым, или указанный сокет находится в недопустимом состоянии. |
WSAEINPROGRESS | Выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова. |
WSAENOTSOCK | Дескриптор не является сокетом. |
Комментарии
Функция WSAEventSelect используется для указания объекта события hEventObject, связанного с выбранным FD_XXX сетевыми событиями lNetworkEvents. Сокет, для которого указан объект события, определяется параметром s . Объект события задается при возникновении любого из назначенных сетевых событий.
Функция WSAEventSelect работает аналогично WSAAsyncSelect. Разница заключается в действиях, выполняемых при возникновении назначенного сетевого события. Функция WSAsyncSelect приводит к публикации сообщения Windows, указанного приложением. WSAEventSelect задает связанный объект события и записывает вхождение этого события во внутреннюю запись сетевого события. Приложение может использовать WSAWaitForMultipleEvents для ожидания или опроса объекта события, а также использовать WSAEnumNetworkEvents для получения содержимого записи внутреннего сетевого события и таким образом определить, какие из назначенных сетевых событий произошли.
Правильный способ сбросить состояние объекта события, используемого с функцией WSAEventSelect , — передать дескриптор объекта события в функцию WSAEnumNetworkEventS впараметре hEventObject . Это приведет к сбросу объекта события и настройке состояния активных событий FD в сокете атомарным образом.
WSAEventSelect — это единственная функция, которая вызывает запись и извлечение сетевых действий и ошибок через WSAEnumNetworkEvents. Ознакомьтесь с описаниями select и WSAAsyncSelect , чтобы узнать, как эти функции сообщают о сетевой активности и ошибках.
Функция WSAEventSelect автоматически устанавливает сокеты в неблокируемый режим независимо от значения lNetworkEvents. Чтобы вернуть сокеты в режим блокировки, сначала необходимо очистить запись события, связанную с сокетами , с помощью вызова WSAEventSelect с параметром lNetworkEvents , равным нулю, а для параметра hEventObject — значение NULL. Затем можно вызвать ioctlsocket или WSAIoctl , чтобы вернуть сокет в режим блокировки.
Параметр lNetworkEvents создается с помощью побитового оператора OR с любым из значений, указанных в следующем списке.
Значение | Значение |
---|---|
FD_READ | Хочет получать уведомление о готовности к чтению. |
FD_WRITE | Хочет получать уведомление о готовности к написанию. |
FD_OOB | Хочет получать уведомление о поступлении данных OOB. |
FD_ACCEPT | Хочет получать уведомления о входящих подключениях. |
FD_CONNECT | Хочет получать уведомление о завершении подключения или операции многоточечего соединения. |
FD_CLOSE | Хочет получать уведомление о закрытии сокета. |
FD_QOS | Хочет получать уведомление об изменениях сокета (QoS. |
FD_GROUP_QOS | Зарезервировано для дальнейшего использования с группами сокетов. Хотите получать уведомление об изменениях качества обслуживания группы сокетов. |
FD_ROUTING_ INTERFACE_CHANGE | Хочет получать уведомления об изменениях интерфейса маршрутизации для указанного назначения. |
FD_ADDRESS_ LIST_CHANGE | Хочет получать уведомление об изменениях локального списка адресов для семейства адресов сокета. |
Выдача WSAEventSelect для сокета отменяет все предыдущие WSAAsyncSelect или WSAEventSelect для того же сокета и очищает запись внутреннего сетевого события. Например, чтобы связать объект события с чтением и записью сетевых событий, приложение должно вызвать WSAEventSelect с FD_READ и FD_WRITE следующим образом:
rc = WSAEventSelect(s, hEventObject, FD_READ|FD_WRITE);
Невозможно указать разные объекты событий для разных сетевых событий. Приведенный ниже код не будет работать. второй вызов отменит эффекты первого, и только сетевое событие FD_WRITE будет связано с hEventObject2:
rc = WSAEventSelect(s, hEventObject1, FD_READ);
rc = WSAEventSelect(s, hEventObject2, FD_WRITE); //bad
Чтобы отменить связь и выбор сетевых событий в сокете, для параметра lNetworkEvents должно быть задано значение 0. В этом случае параметр hEventObject будет игнорироваться.
rc = WSAEventSelect(s, hEventObject, 0);
Закрытие сокета с помощью closesocket также отменяет связь и выбор сетевых событий, указанных в WSAEventSelect для сокета. Однако приложение по-прежнему должно вызывать WSACloseEvent , чтобы явным образом закрыть объект события и освободить все ресурсы.
Сокет, созданный при вызове функции accept , имеет те же свойства, что и сокет прослушивания, используемый для ее принятия. Любой набор выбора связей WSAEventSelect и сетевых событий для прослушивающего сокета применяется к принятому сокету. Например, если прослушивающий сокет имеет связь WSAEventSelecthEventObject с FD_ACCEPT, FD_READ и FD_WRITE, то любой сокет, принятый в этом сокете прослушивания, также будет иметь FD_ACCEPT, FD_READ и FD_WRITE сетевые события, связанные с тем же hEventObject. Если требуются другие события hEventObject или сетевые события, приложение должно вызвать WSAEventSelect, передав принятый сокет и нужные новые сведения.
Пример кода
В следующем примере показано использование функции WSAEventSelect .//-------------------------
// Declare and initialize variables
SOCKET ListenSocket;
WSAEVENT NewEvent;
sockaddr_in InetAddr;
//-------------------------
// Initialize listening socket
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//-------------------------
// Bind listening socket
InetAddr.sin_family = AF_INET;
InetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
InetAddr.sin_port = htons(27015);
bind (ListenSocket, (SOCKADDR *) &InetAddr, sizeof(InetAddr));
//-------------------------
// Create new event
NewEvent = WSACreateEvent();
//-------------------------
// Associate event types FD_ACCEPT and FD_CLOSE
// with the listening socket and NewEvent
WSAEventSelect( ListenSocket, NewEvent, FD_ACCEPT | FD_CLOSE);
//----------------------
// Listen for incoming connection requests
// on the created socket
if (listen( ListenSocket, SOMAXCONN ) == SOCKET_ERROR)
printf("Error listening on socket.\n");
printf("Listening on socket...\n");
// Need an event handler added to handle connection requests
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] |
Целевая платформа | Windows |
Header | winsock2.h |
Библиотека | Ws2_32.lib |
DLL | Ws2_32.dll |