Функция WSAAsyncSelect (winsock.h)
[Функция WSAsyncSelect доступна для использования в операционных системах, указанных в разделе Требования. В последующих версиях он может быть изменен или недоступен. Вместо использования операций ввода-вывода в стиле выбора используйте перекрывающиеся объекты ввода-вывода и объекты событий с WinSock2.]
Функция WSAsyncSelect запрашивает уведомления Windows на основе сообщений о сетевых событиях для сокета.
Синтаксис
int WSAAsyncSelect(
[in] SOCKET s,
[in] HWND hWnd,
[in] u_int wMsg,
[in] long lEvent
);
Параметры
[in] s
Дескриптор, определяющий сокет, для которого требуется уведомление о событии.
[in] hWnd
Дескриптор, определяющий окно, которое будет получать сообщение при возникновении сетевого события.
[in] wMsg
Сообщение, которое должно быть получено при возникновении сетевого события.
[in] lEvent
Битовая маска, задающая сочетание сетевых событий, в которых заинтересовано приложение.
Возвращаемое значение
Если функция WSAsyncSelect завершается успешно, возвращаемое значение равно нулю при условии успешного объявления приложения о заинтересованности в наборе сетевых событий. В противном случае возвращается значение SOCKET_ERROR, а определенный номер ошибки можно получить, вызвав WSAGetLastError.
Код ошибки | Значение |
---|---|
Перед использованием этой функции должен быть выполнен успешный вызов WSAStartup . | |
Произошел сбой сетевой подсистемы. | |
Один из указанных параметров был недопустимым, например дескриптор окна, не ссылающийся на существующее окно, или указанный сокет находится в недопустимом состоянии. | |
Выполняется блокирующий вызов Windows Sockets 1.1 или поставщик услуг по-прежнему обрабатывает функцию обратного вызова. | |
Дескриптор не является сокетом. |
При получении сообщения в окне приложения можно задать дополнительные коды ошибок. Этот код ошибки извлекается из lParam в ответном сообщении с помощью макроса WSAGETSELECTERROR . Возможные коды ошибок для каждого сетевого события перечислены в следующей таблице.
Событие: FD_CONNECT
Код ошибки | Значение |
---|---|
WSAEAFNOSUPPORT | Адреса из заданного семейства адресов не могут использоваться с этим сокетом. |
WSAECONNREFUSED | Попытка подключения отклонена. |
WSAENETUNREACH | В настоящее время сеть недоступна с этого узла. |
WSAEFAULT | Недопустимый параметр namelen . |
WSAEINVAL | Сокет уже привязан к адресу. |
WSAEISCONN | Сокет уже подключен. |
WSAEMFILE | Больше нет доступных дескрипторов файлов. |
WSAENOBUFS | Нет свободного места в буфере. Не удается подключить сокет. |
WSAENOTCONN | Сокет не подключен. |
WSAETIMEDOUT | Попытка подключения истекло, не устанавливая подключение. |
Событие: FD_CLOSE
Код ошибки | Значение |
---|---|
WSAENETDOWN | Произошел сбой сетевой подсистемы. |
WSAECONNRESET | Подключение было сброшено удаленной стороной. |
WSAECONNABORTED | Подключение было прервано из-за истечения времени ожидания или другого сбоя. |
Код ошибки | Значение |
---|---|
WSAENETDOWN | Произошел сбой сетевой подсистемы. |
Событие: FD_ROUTING_INTERFACE_CHANGE
Код ошибки | Значение |
---|---|
WSAENETUNREACH | Указанное назначение больше недоступно. |
WSAENETDOWN | Произошел сбой сетевой подсистемы. |
Комментарии
Функция WSAsyncSelect используется для запроса того, чтобы WS2_32.DLL отправляли сообщение в окно hWnd при обнаружении любого сетевого события, указанного параметром lEvent . Сообщение, которое должно быть отправлено, указывается параметром wMsg . Сокет, для которого требуется уведомление, определяется параметром s .
Функция WSAsyncSelect автоматически устанавливает сокеты в неблокируемый режим независимо от значения lEvent. Чтобы вернуть сокеты в режим блокировки, сначала необходимо очистить запись события, связанную с сокетами , с помощью вызова WSAsyncSelect с параметром lEvent , равным нулю. Затем можно вызвать ioctlsocket или WSAIoctl , чтобы вернуть сокет в режим блокировки. Дополнительные сведения о том, как вернуть неблокирующий сокет в режим блокировки, см. в разделе Функции ioctlsocket и WSAIoctl .
Параметр lEvent создается с помощью побитового оператора OR с любым значением, перечисленным в следующей таблице.
Значение | Значение |
---|---|
FD_READ | Задайте для получения уведомления о готовности к чтению. |
FD_WRITE | Хочет получать уведомление о готовности к написанию. |
FD_OOB | Хочет получать уведомления о поступлении данных OOB. |
FD_ACCEPT | Хочет получать уведомления о входящих подключениях. |
FD_CONNECT | Хочет получать уведомление о завершении подключения или операции многоточечных соединений. |
FD_CLOSE | Хочет получать уведомление о закрытии сокета. |
FD_QOS | Хочет получать уведомления об изменениях качества обслуживания сокета (QoS). |
FD_GROUP_QOS | Хочет получать уведомления об изменениях качества обслуживания (QoS) сокет-групп (зарезервированных для будущего использования с группами сокетов). Зарезервировано. |
FD_ROUTING_INTERFACE_CHANGE | Хочет получать уведомление об изменениях интерфейса маршрутизации для указанных назначений. |
FD_ADDRESS_LIST_CHANGE | Хочет получать уведомление об изменениях локального списка адресов для семейства протоколов сокетов. |
Выдача WSAsyncSelect для сокета отменяет все предыдущие WSAAsyncSelect или WSAEventSelect для того же сокета. Например, чтобы получать уведомления о чтении и записи, приложение должно вызвать WSAsyncSelect с FD_READ и FD_WRITE следующим образом:
rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);
Невозможно указать разные сообщения для разных событий. Приведенный ниже код не будет работать. второй вызов отменит эффекты первого, и только FD_WRITE события будут сообщаться с сообщением wMsg2:
rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);
Чтобы отменить все уведомления о том, что сокеты Windows не должны отправлять дальнейшие сообщения, связанные с сетевыми событиями в сокете, для параметра lEvent задано значение 0.
rc = WSAAsyncSelect(s, hWnd, 0, 0);
Хотя WSAsyncSelect немедленно отключает отправку сообщений о событиях для сокета в этом экземпляре, вполне возможно, что сообщения могут находиться в очереди сообщений приложения. Поэтому приложение должно быть готово к получению сообщений о сетевых событиях даже после отмены. Закрытие сокета с помощью closesocket также отменяет отправку сообщений WSAsyncSelect , но те же предупреждения о сообщениях в очереди по-прежнему применяются.
Сокет, созданный функцией accept , имеет те же свойства, что и сокет прослушивания, используемый для его принятия. Следовательно, события WSAsyncSelect, заданные для прослушивающего сокета, также применяются к принятому сокету. Например, если прослушивающий сокет содержит события WSAAsyncSelectFD_ACCEPT, FD_READ и FD_WRITE, то любой сокет, принятый в этом сокете прослушивания, также будет иметь события FD_ACCEPT, FD_READ и FD_WRITE с тем же значением wMsg , которое используется для сообщений. Если требуются другие события wMsg или , приложение должно вызвать WSAsyncSelect, передав принятый сокет и нужные новые данные.
Если одно из назначенных сетевых событий происходит в указанных сокетах, окно приложения hWnd получает сообщение wMsg. Параметр wParam определяет сокет, в котором произошло сетевое событие. Низкое слово lParam указывает сетевое событие, которое произошло. Высокое слово lParam содержит любой код ошибки. Код ошибки — любая ошибка, определенная в Winsock2.h.
#include <windows.h>
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
Использование этих макросов обеспечит максимальную переносимость исходного кода для приложения.
Возможные коды сетевых событий, которые могут быть возвращены, перечислены в следующей таблице.
Значение | Значение |
---|---|
FD_READ | Сокеты готовы к чтению. |
FD_WRITE | Сокеты готовы к записи. |
FD_OOB | Данные OOB готовы к чтению в сокетах |
FD_ACCEPT | Сокеты готовы к принятию нового входящего подключения. |
FD_CONNECT | Операция подключения или многоточечных соединений , инициированная по завершению сокетов . |
FD_CLOSE | Подключение, определенное по сокетам , было закрыто. |
FD_QOS | Качество обслуживания, связанное с сокетами , изменилось. |
FD_GROUP_QOS | Зарезервировано. Качество обслуживания, связанное с группой сокетов , к которой принадлежит , изменилось (зарезервировано для будущего использования с группами сокетов). |
FD_ROUTING_INTERFACE_CHANGE | Изменен локальный интерфейс, который должен использоваться для отправки в указанное место назначения. |
FD_ADDRESS_LIST_CHANGE | Изменен список адресов семейства протоколов сокетов, к которым может привязаться клиент приложения. |
Хотя WSAAsyncSelect можно вызывать с интересом к нескольким событиям, окно приложения будет получать одно сообщение для каждого сетевого события.
Как и в случае с функцией select , WSAsyncSelect часто используется для определения того, когда может быть выполнена операция передачи данных (отправка или восстановление) с ожиданием немедленного успеха. Тем не менее, надежное приложение должно быть готово к тому, что оно может получить сообщение и выдать вызов Windows Sockets 2, который немедленно возвращает WSAEWOULDBLOCK . Например, возможна следующая последовательность событий:
- Данные поступают в сокеты; Сообщения WSAsyncSelect для сокетов Windows 2
- Приложение обрабатывает другое сообщение
- Во время обработки приложение выдает
ioctlsocket(s, FIONREAD...)
и замечает, что данные готовы к чтению - Приложение выдает для
recv(s,...)
чтения данных - Циклы приложения для обработки следующего сообщения, в конечном итоге достигая сообщения WSAsyncSelect , указывающего, что данные готовы к чтению
- Проблемы
recv(s,...)
с приложением, которые завершаются сбоем с ошибкой WSAEWOULDBLOCK.
WS2_32.DLL не будет постоянно заполнять приложение сообщениями для определенного сетевого события. После успешной публикации уведомления о конкретном событии в окне приложения дальнейшие сообщения для этого сетевого события не будут отправляться в окно приложения, пока приложение не выполнит вызов функции, который неявно повторно включает уведомление об этом сетевом событии.
Событие | Функция reenabling |
---|---|
FD_READ | recv, recvfrom, WSARecv или WSARecvFrom. |
FD_WRITE | send, sendto, WSASend или WSASendTo. |
FD_OOB | recv, recvfrom, WSARecv или WSARecvFrom. |
FD_ACCEPT | accept или WSAAccept, если код ошибки не WSATRY_AGAIN , указывающий, что функция условия вернула CF_DEFER. |
FD_CONNECT | Нет. |
FD_CLOSE | Нет. |
FD_QOS | WSAIoctl с командой SIO_GET_QOS. |
FD_GROUP_QOS | Зарезервировано. WSAIoctl с командой SIO_GET_GROUP_QOS (зарезервировано для будущего использования с группами сокетов). |
FD_ROUTING_INTERFACE_CHANGE | WSAIoctl с командой SIO_ROUTING_INTERFACE_CHANGE. |
FD_ADDRESS_LIST_CHANGE | WSAIoctl с командой SIO_ADDRESS_LIST_CHANGE. |
Любой вызов подпрограммы повторного создания, даже сбой, приводит к повторной публикации сообщений для соответствующего события.
Для событий FD_READ, FD_OOB и FD_ACCEPT публикация сообщений активируется на уровне. Это означает, что если вызывается подпрограмма повторного добавления и соответствующее условие по-прежнему выполняется после вызова, в приложение отправляется сообщение WSAsyncSelect . Это позволяет приложению управлять событиями и не беспокоиться о количестве данных, поступающих в любой момент времени. Рассмотрим следующую последовательность:
- Стек сетевого транспорта получает 100 байт данных в сокетах и заставляет Windows Sockets 2 публиковать FD_READ сообщение.
- Приложение выдает recv( s, buffptr, 50, 0) для чтения 50 байт.
- Публикуется еще одно сообщение FD_READ , так как все еще есть данные для чтения.
События FD_QOS и FD_GROUP_QOS считаются пограничными. Сообщение будет опубликовано ровно один раз при изменении качества обслуживания. Дальнейшие сообщения не будут выводиться до тех пор, пока поставщик не обнаружит дальнейшее изменение качества обслуживания или приложение не пересматривает качество обслуживания для сокета.
Сообщение FD_ROUTING_INTERFACE_CHANGE отправляется, когда локальный интерфейс, который должен использоваться для достижения назначения, указанного в WSAIoctl , с SIO_ROUTING_INTERFACE_CHANGE изменения после выдачи такого IOCTL.
Сообщение FD_ADDRESS_LIST_CHANGE публикуется, когда список адресов, к которым приложение может привязаться, изменяется после выпуска WSAIoctl с SIO_ADDRESS_LIST_CHANGE.
Если произошло какое-либо событие, когда приложение вызывает WSAsyncSelect или вызывается функция повторного запуска, сообщение публикуется соответствующим образом. Например, рассмотрим следующую последовательность:
- Вызовы приложения прослушивают.
- Запрос на подключение получен, но еще не принят.
- Приложение вызывает WSAsyncSelect , указывая, что требуется получать FD_ACCEPT сообщения для сокета. Из-за сохраняемости событий Windows Sockets 2 немедленно публикует сообщение FD_ACCEPT .
Событие FD_WRITE обрабатывается немного иначе. Сообщение FD_WRITE публикуется, когда сокет сначала подключается с помощью connect или WSAConnect (после FD_CONNECT, если также зарегистрирован) или принимается с помощью accept или WSAAccept, а затем после сбоя операции отправки с WSAEWOULDBLOCK и буферное пространство становится доступным. Таким образом, приложение может предположить, что отправка возможна, начиная с первого FD_WRITE сообщения и длится до тех пор, пока отправка не вернет WSAEWOULDBLOCK. После такого сбоя приложение получит уведомление о том, что отправка снова возможна с помощью FD_WRITE сообщения.
Событие 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. Это приводит к тому, что удаленный конец выполняет завершение работы на стороне отправки или closesocket. FD_CLOSE следует публиковать только после того, как все данные считываются из сокета, но приложение должно проверка для оставшихся данных при получении FD_CLOSE, чтобы избежать любой возможности потери данных.
Имейте в виду, что приложение получит FD_CLOSE сообщение, указывающее на закрытие виртуального канала, и только если все полученные данные были прочитаны, если это корректное закрытие. Он не получит FD_READ сообщение, указывающее на это условие.
Сообщение FD_QOS или FD_GROUP_QOS публикуется при изменении любого параметра в спецификации потока, связанной с сокетами или группой сокетов, к которой принадлежит сокет. Приложения должны использовать WSAIoctl с командой SIO_GET_QOS или SIO_GET_GROUP_QOS, чтобы получить текущее качество обслуживания для сокетов или групп сокетов, к которым принадлежит соответственно .
События FD_ROUTING_INTERFACE_CHANGE и FD_ADDRESS_LIST_CHANGE также считаются пограничными. Сообщение будет опубликовано ровно один раз, когда произойдет изменение после того, как приложение запросит уведомление, выполнив WSAIoctl с SIO_ROUTING_INTERFACE_CHANGE или SIO_ADDRESS_LIST_CHANGE соответствующим образом. Дальнейшие сообщения не будут приходить до тех пор, пока приложение не переидаст IOCTL и не будет обнаружено другое изменение, так как был выдан IOCTL.
Ниже приведена сводка событий и условий для каждого асинхронного уведомления.
-
FD_READ:
- При вызове метода WSAsyncSelect , если есть данные, доступные для получения в настоящее время.
- При поступлении данных, если FD_READ еще не опубликовано.
- После вызова recv или recvfrom с MSG_PEEK или без нее), если данные по-прежнему доступны для получения.
Примечание Если параметр setsockopt SO_OOBINLINE включен, данные включают как обычные данные, так и данные OOB в указанных выше экземплярах.
-
FD_WRITE:
- При вызове метода WSAsyncSelect можно ли выполнить отправку или отправку .
- После подключения или принятия вызова, когда подключение установлено.
- После отправки или отправки сбойс WSAEWOULDBLOCK, когда отправка или отправка, скорее всего, завершится успешно.
- После привязки к сокету без подключения. FD_WRITE может возникнуть или не происходить в настоящее время (зависит от реализации). В любом случае сокет без подключения всегда доступен для записи сразу после операции привязки .
-
FD_OOB: допустимо только в том случае, если параметр setsockopt SO_OOBINLINE отключен (по умолчанию).
- Если при вызове метода WSAAsyncSelect есть данные OOB, доступные для получения с флагом MSG_OOB.
- При поступлении данных OOB, если FD_OOB еще не опубликовано.
- После вызова recv или recvfrom с флагом MSG_OOB или без нее, если данные OOB по-прежнему доступны для получения.
-
FD_ACCEPT:
- При вызове метода WSAAsyncSelect , если в настоящее время есть запрос на подключение, доступный для принятия.
- При поступлении запроса на подключение, если FD_ACCEPT еще не опубликовано.
- После вызова accept , если есть другой запрос на подключение, доступный для принятия.
-
FD_CONNECT:
- При вызове метода WSAsyncSelect , если подключение установлено в данный момент.
- После вызова подключения подключение устанавливается, даже если подключение выполняется немедленно, как это характерно для сокета датаграммы.
- После вызова WSAJoinLeaf, когда операция соединения завершается.
- После подключения был вызван WSAConnect или WSAJoinLeaf с неблокированным сокетом, ориентированным на подключение. Исходная операция была возвращена с определенной ошибкой WSAEWOULDBLOCK, но сетевая операция была выполнена. Независимо от того, завершается ли операция успешной или нет, когда результат определен, FD_CONNECT происходит. Клиент должен проверка код ошибки, чтобы определить, был ли результат успешным или неудачным.
-
FD_CLOSE: допустимо только для сокетов, ориентированных на подключение (например, SOCK_STREAM).
- При вызове метода WSAAsyncSelect , если подключение к сокету закрыто.
- После того, как удаленная система инициировала корректное закрытие, если данные в настоящее время недоступны для получения (имейте в виду, что если данные были получены и ожидают чтения, когда удаленная система инициирует корректное закрытие, FD_CLOSE не будет доставлена до тех пор, пока не будут прочитаны все ожидающие данные).
- После того как локальная система инициирует корректное закрытие с завершением работы , и удаленная система ответила уведомлением "Конец данных" (например, TCP FIN), если данные в настоящее время недоступны для получения.
- Когда удаленная система завершает подключение (например, отправлено TCP RST), и lParam будет содержать значение ошибки WSAECONNRESET .
ПримечаниеFD_CLOSE не публикуется после вызова closesocket .
-
FD_QOS:
- При вызове метода WSAsyncSelect , если качество обслуживания, связанного с сокетом, было изменено.
- После вызова WSAIoctl с SIO_GET_QOS при изменении качества обслуживания.
- FD_GROUP_QOS: зарезервировано.
-
FD_ROUTING_INTERFACE_CHANGE:
- После вызова WSAIoctl с SIO_ROUTING_INTERFACE_CHANGE, когда изменяется локальный интерфейс, который должен использоваться для достижения назначения, указанного в IOCTL.
-
FD_ADDRESS_LIST_CHANGE:
- После вызова WSAIoctl с SIO_ADDRESS_LIST_CHANGE при изменении списка локальных адресов, к которым может привязаться приложение.
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Windows 2000 Professional [только классические приложения] |
Минимальная версия сервера | Windows 2000 Server [только классические приложения] |
Целевая платформа | Windows |
Header | winsock.h (включая Winsock2.h) |
Библиотека | Ws2_32.lib |
DLL | Ws2_32.dll |