Поделиться через


Функция обратного вызова LPWSPASYNCSELECT (ws2spi.h)

Функция LPWSPAsyncSelect запрашивает уведомление о событиях на основе сообщений Windows о сетевых событиях для сокета.

Синтаксис

LPWSPASYNCSELECT Lpwspasyncselect;

int Lpwspasyncselect(
  [in]  SOCKET s,
  [in]  HWND hWnd,
  [in]  unsigned int wMsg,
  [in]  long lEvent,
  [out] LPINT lpErrno
)
{...}

Параметры

[in] s

Дескриптор, определяющий сокет, для которого требуется уведомление о событии.

[in] hWnd

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

[in] wMsg

Сообщение, отправляемое при возникновении сетевого события.

[in] lEvent

Битовая маска, задающая сочетание сетевых событий, в которых заинтересован клиент интерфейса поставщика сокетов Windows (SPI). Создается с помощью побитового оператора 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
Выдает уведомление об изменении локального списка адресов для семейства протоколов сокета.

[out] lpErrno

Указатель на код ошибки. Дополнительные сведения см. в разделе Возвращаемое значение .

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

Возвращаемое значение равно нулю, если клиент Windows Sockets SPI успешно объявляет интерес к набору сетевых событий. В противном случае возвращается значение, SOCKET_ERROR, и в lpErrno доступен определенный код ошибки.

Код ошибки Значение
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAEINVAL
Указывает, что один из указанных параметров был недопустимым, например, дескриптор окна, не ссылающийся на существующее окно, или указанный сокет находится в недопустимом состоянии.
WSAEINPROGRESS
Выполняется блокирующий вызов Windows Sockets или поставщик услуг по-прежнему обрабатывает функцию обратного вызова.
WSAENOTSOCK
Дескриптор не является сокетом.

Дополнительные коды ошибок, которые можно задать (в высоком слове lParam в сообщении) при получении сообщения в окне приложения, см. в примечаниях.

Комментарии

Эта функция используется для запроса на отправку поставщиком услуг сообщения Windows в окно клиента hWnd всякий раз, когда поставщик услуг обнаруживает какие-либо сетевые события, указанные аргументом lEvent . Поставщик услуг должен использовать функцию WPUPostMessage для публикации сообщения. Отправляемые сообщения задаются параметром wMsg . Сокет, для которого требуется уведомление, определяется по s.

Эта функция автоматически устанавливает сокеты в режим неблокировки, независимо от значения lEvent. Сведения о том, как вернуть сокет в режим блокировки, см. в разделе LPWSPIoctl .

Вызов LPWSPAsyncSelect для сокета отменяет все предыдущие LPWSPAsyncSelect или LPWSPEventSelect для того же сокета. Например, чтобы получать уведомления о чтении и записи, клиент SPI сокетов Windows должен вызвать LPWSPAsyncSelect с FD_READ и FD_WRITE, как показано ниже.

rc = WSPAsyncSelect(s, hWnd, wMsg, FD_READ | FD_WRITE, &error);

Невозможно указать разные сообщения для разных событий. Следующий код не будет работать. второй вызов отменяет эффекты первого, и единственной связью будет событие FD_WRITE, связанное с wMsg2.

// Incorrect example.
rc = WSPAsyncSelect(s, hWnd, wMsg1, FD_READ, &error);
rc = WSPAsyncSelect(s, hWnd, wMsg2, FD_WRITE, &error);

Чтобы отменить все уведомления (т. е. указать, что поставщик услуг не должен отправлять больше сообщений, связанных с сетевыми событиями в сокете), установите для параметра lEvent значение 0.

rc = WSPAsyncSelect(s, hWnd, 0, 0, &error);

Так как сокет LPWSPAccept'ed имеет те же свойства, что и сокет прослушивания, используемый для его принятия, любые события LPWSPAsyncSelect, заданные для сокета прослушивания, применяются к принятому сокету. Например, если прослушивающий сокет содержит события LPWSPAsyncSelect FD_ACCEPT, FD_READ и FD_WRITE, то любой сокет, принятый в этом сокете прослушивания, также будет иметь события FD_ACCEPT, FD_READ и FD_WRITE с тем же значением wMsg , которое используется для сообщений. Если требуются другие события wMsg или , клиент SPI сокетов Windows должен вызвать LPWSPAsyncSelect, передав принятый сокет и необходимые новые сведения.

Когда одно из назначенных сетевых событий происходит в указанных сокетах, поставщик услуг использует WPUPostMessage для отправки сообщения wMsg в окно hWnd клиента SPI windows Sockets. В отправленном сообщении аргумент wParam определяет сокет, в котором произошло сетевое событие. Низкое слово lParam указывает сетевое событие, которое произошло. Ниже приведены возможные коды сетевых событий.

Значение Значение
FD_READ Сокет готов к чтению
FD_WRITE Сокет готов к записи
FD_OOB Внеполосные данные готовы к чтению в сокетах
FD_ACCEPT Socket s готов принять новое входящее подключение
FD_CONNECT Подключение, которое было инициировано в сокетах, завершено
FD_CLOSE Подключение, определенное по сокетам, закрыто
FD_QOS Изменилось качество обслуживания, связанного с сокетами
FD_GROUP_QOS Зарезервировано для будущего использования с группами сокетов: изменилось качество обслуживания, связанного с группой сокетов, к которой принадлежит сокет.
FD_ROUTING_INTERFACE_CHANGE Изменен локальный интерфейс, который должен использоваться для отправки в указанное место назначения.
FD_ADDRESS_LIST_CHANGE Изменился список адресов семейства протоколов сокета, к которым может привязаться клиент SPI сокетов Windows.

Высокое слово lParam содержит любой код ошибки (его можно извлечь с помощью макроса WSAGETSELECTERROR ). Код ошибки — любая ошибка, определенная в ws2spi.h. В следующей таблице перечислены возможные коды ошибок для каждого сетевого события.

Событие: FD_CONNECT

Код ошибки Значение
WSAEAFNOSUPPORT
Адреса из заданного семейства адресов не могут использоваться с этим сокетом.
WSAECONNREFUSED
Попытка подключения была отклонена.
WSAENETUNREACH
В настоящее время сеть недоступна с этого узла.
WSAEFAULT
Недопустимый параметр namelen .
WSAEINVAL
Сокет уже привязан к адресу.
WSAEISCONN
Сокет уже подключен.
WSAEMFILE
Больше нет доступных дескрипторов файлов.
WSAENOBUFS
Нет свободного места в буфере. Не удается подключить сокет.
WSAENOTCONN
Сокет не подключен.
WSAETIMEDOUT
Истекло время ожидания попытки подключения без установления подключения.

Событие: FD_CLOSE

Код ошибки Значение
WSAENETDOWN
Произошел сбой сетевой подсистемы.
WSAECONNRESET
Подключение было сброшено удаленной стороной.
WSAECONNABORTED
Подключение было прервано из-за истечения времени ожидания или другого сбоя.

Событие...: FD_ACCEPT, FD_ADDRESS_LIST_CHANGE, FD_GROUP_QOS, FD_OOB, FD_QOS, FD_READ, FD_WRITE

Код ошибки Значение
WSAENETDOWN
Произошел сбой сетевой подсистемы.

Событие: FD_ROUTING_INTERFACE_CHANGE

Код ошибки Значение
WSAENETUNREACH
Указанное назначение больше недоступно.
WSAENETDOWN
Произошел сбой сетевой подсистемы.

Хотя LPWSPAsyncSelect можно вызывать с интересом к нескольким событиям, поставщик услуг выдает одно и то же сообщение Windows для каждого события.

Поставщик сокетов Windows 2 не должен постоянно заполнять клиент Windows Sockets SPI сообщениями для определенного сетевого события. После успешной публикации уведомления о конкретном событии в окне клиента SPI сокетов Windows никакие дополнительные сообщения для этого сетевого события не будут отправляться в окно клиента WINDOWS Sockets SPI до тех пор, пока клиент Windows Sockets SPI не выполнит вызов функции, который неявно активирует уведомление об этом сетевом событии.

Сетевое событие Повторное включение функции
FD_READ LPWSPRecv или LPWSPRecvFrom
FD_WRITE LPWSPSend или LPWSPSendTo
FD_OOB LPWSPRecv или LPWSPRecvFrom
FD_ACCEPT LPWSPAccept, если код ошибки не WSATRY_AGAIN, указывающий, что функция условия вернула CF_DEFER
FD_CONNECT None
FD_CLOSE None
FD_QOS LPWSPIoctl с SIO_GET_QOS
FD_GROUP_QOS Зарезервировано для использования в будущем с группами сокетов: LPWSPIoctl с SIO_GET_GROUP_QOS
FD_ROUTING_INTERFACE_CHANGE LPWSPIoctl с командой SIO_ROUTING_INTERFACE_CHANGE
FD_ADDRESS_LIST_CHANGE LPWSPIoctl с командой SIO_ADDRESS_LIST_CHANGE

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

Для событий FD_READ, FD_OOB и FD_ACCEPT публикация сообщений активируется на уровне. Это означает, что если вызывается процедура повторного включения и соответствующее условие по-прежнему выполняется после вызова, сообщение LPWSPAsyncSelect отправляется клиенту SPI windows Sockets.

События FD_QOS и FD_GROUP_QOS считаются запущенными по краю. Сообщение будет опубликовано ровно один раз при изменении QOS. Дальнейшие сообщения не будут выводиться, пока поставщик не обнаружит дальнейшее изменение в QOS или клиент Windows Sockets SPI не пересматривает QOS для сокета.

События FD_ROUTING_INTERFACE_CHANGE и FD_ADDRESS_LIST_CHANGE также считаются запущенными по краям . Сообщение будет опубликовано ровно один раз, когда произойдет изменение после того, как клиент WINDOWS Sockets SPI запросит уведомление путем выдачи WSAIoctl с SIO_ROUTING_INTERFACE_CHANGE или SIO_ADDRESS_LIST_CHANGE соответствующим образом. Дальнейшие сообщения не будут выдаваться до тех пор, пока клиент WINDOWS Sockets SPI повторно не выдаст IOCTL и не будет обнаружено другое изменение с момента выдачи IOCTL.

Если какое-либо событие уже произошло при вызове клиентом SPI сокетов Windows LPWSPAsyncSelect или при вызове функции повторного включения, сообщение публикуется соответствующим образом. Например, рассмотрим следующую последовательность.

  1. Клиент WINDOWS Sockets SPI вызывает LPWSPListen.
  2. Запрос на подключение получен, но еще не принят.
  3. Клиент SPI сокетов Windows вызывает LPWSPAsyncSelect , указывая, что он хочет получать FD_ACCEPT сообщения для сокета. Из-за сохраняемости событий поставщик службы WinSock немедленно публикует FD_ACCEPT сообщение.

Событие FD_WRITE обрабатывается немного иначе. Сообщение FD_WRITE публикуется, когда сокет сначала подключается к LPWSPConnect (после FD_CONNECT, если также зарегистрирован) или принимается с помощью LPWSPAccept, а затем после того, как LPWSPSend или LPWSPSendTo завершается сбоем с WSAEWOULDBLOCK и буферное пространство становится доступным. Таким образом, клиент SPI-сокетов Windows может предположить, что отправка возможна, начиная с первого FD_WRITE сообщения и продлится до тех пор, пока отправка не вернет WSAEWOULDBLOCK. После такого сбоя клиент SPI сокетов Windows получит уведомление о том, что отправка снова возможна с помощью FD_WRITE сообщения.

Событие FD_OOB используется только в том случае, если сокет настроен для получения данных по отдельности. Если сокет настроен для получения внеполосных данных в строке, то внеполосные (ускоряемые) данные обрабатываются как обычные данные, и клиент WINDOWS Sockets SPI должен регистрировать интерес к событиям FD_READ, а не к событиям FD_OOB.

Код ошибки в сообщении FD_CLOSE указывает, было ли закрытие сокета корректно или прервано. Если код ошибки равен 0, закрытие было корректно. Если код ошибки — WSAECONNRESET, то виртуальный канал сокета был сброшен. Это относится только к сокетам, ориентированным на подключение, таким как SOCK_STREAM.

Сообщение FD_CLOSE публикуется при получении указания на закрытие виртуального канала, соответствующего сокету. С точки зрения TCP это означает, что FD_CLOSE отправляется, когда подключение переходит в состояния TIME WAIT или CLOSE WAIT. Это происходит из-за того, что удаленный конец выполняет LPWSPShutdown на стороне отправки или LPWSPCloseSocket. Правильно, чтобы FD_CLOSE публиковаться только после того, как все данные считываются из сокета.

В случае корректного закрытия поставщик услуг должен отправить FD_CLOSE сообщение, указывающее на закрытие виртуального канала только после считывания всех полученных данных. Оно не должно отправлять FD_READ сообщение, указывающее на это условие.

Сообщение FD_QOS или FD_GROUP_QOS публикуется при изменении любого поля в спецификации потока, связанной с сокетами, или в группе сокетов , к которой они принадлежат соответственно. Поставщик услуг должен обновить сведения о QOS, доступные клиенту через LPWSPIoctl , с помощью SIO_GET_QOS и (или) SIO_GET_GROUP_QOS.

Сообщение FD_ROUTING_INTERFACE_CHANGE публикуется, когда локальный интерфейс, который должен использоваться для достижения назначения, указанного в LPWSPIoctl , с SIO_ROUTING_INTERFACE_CHANGE изменения после выдачи такого IOCTL.

Сообщение FD_ADDRESS_LIST_CHANGE публикуется, когда список адресов, к которым клиент spi может привязать сокеты Windows, изменяется послевыдачи LPWSPIoctl с SIO_ADDRESS_LIST_CHANGE.

Ниже приведена сводка событий и условий для каждого асинхронного уведомления.

FD_READ

  1. Если вызывается LPWSPAsyncSelect , если в настоящее время доступны данные для получения.
  2. При поступлении данных, если FD_READ еще не опубликовано.
  3. После вызова LPWSPRecv или LPWSPRecvFrom (с MSG_PEEK или без него), если данные по-прежнему доступны для получения.

Если SO_OOBINLINE LPWSPSetSockOpt включен, данные включают как обычные, так и внештатные (OOB) данные в указанных выше экземплярах.

FD_WRITE

  1. Если вызывается LPWSPAsyncSelect , возможно ли LPWSPSend или LPWSPSendTo .
  2. После вызова LPWSPConnect или LPWSPAccept при установке подключения.
  3. После сбоя LPWSPSend или LPWSPSendTo с WSAEWOULDBLOCK, если LPWSPSend или LPWSPSendTo , скорее всего, завершится успешно.
  4. После LPWSPBind в сокете без подключения. FD_WRITE может произойти или не происходить в настоящее время (зависит от реализации). В любом случае сокет без подключения всегда доступен для записи сразу после LPWSPBind.

FD_OOB (допустимо только в том случае, если SO_OOBINLINE LPWSPSetSockOpt отключен (по умолчанию))

  1. При вызове LPWSPAsyncSelect , если в настоящее время доступны данные OOB для получения с флагом MSG_OOB.
  2. При поступлении данных OOB, если FD_OOB еще не опубликовано.
  3. После вызова LPWSPRecv или LPWSPRecvFrom с флагом MSG_OOB или без него, если данные OOB по-прежнему доступны для получения.

FD_ACCEPT

  1. Если вызывается LPWSPAsyncSelect , если в настоящее время доступен запрос на подключение для принятия.
  2. При поступлении запроса на подключение, если FD_ACCEPT еще не опубликовано.
  3. Если после вызова LPWSPAccept имеется другой запрос на подключение, который можно принять.

FD_CONNECT

  1. При вызове LPWSPAsyncSelect , если в настоящее время установлено подключение.
  2. После вызова LPWSPConnect при установке подключения (даже при немедленном завершении LPWSPConnect , как это обычно происходит с сокетом датаграммы), и даже при немедленном сбое).
  3. После вызова WSPJoinLeaf по завершении операции соединения.
  4. После подключения был вызван WSAConnect или WSPJoinLeaf с неблокирующим сокетом, ориентированным на подключение. Исходная операция была возвращена с определенной ошибкой WSAEWOULDBLOCK, но сетевая операция была выполнена. Независимо от того, завершается ли операция успешной или нет, когда результат определен, FD_CONNECT происходит. Клиент должен проверка код ошибки, чтобы определить, был ли результат успешным или неудачным.

FD_CLOSE (допустимо только для сокетов, ориентированных на подключение (например, SOCK_STREAM))

  1. При вызове LPWSPAsyncSelect , если подключение к сокету закрыто.
  2. После того как удаленная система инициировала корректное закрытие, когда данные в настоящее время недоступны для получения (если данные получены и ожидают чтения, когда удаленная система инициирует корректное закрытие, FD_CLOSE не доставляется до тех пор, пока не будут прочитаны все ожидающие данные).
  3. После того как локальная система инициирует корректное закрытие с помощью LPWSPShutdown и удаленная система ответила уведомлением об окончании данных (например, TCP FIN), если данные в настоящее время недоступны для получения.
  4. Когда удаленная система прервет подключение (например, отправлено TCP RST), и lParam будет содержать значение ошибки WSAECONNRESET.

FD_CLOSE не публикуется после вызова LPWSPCloseSocket .

FD_QOS

  1. При вызове LPWSPAsyncSelect , если QOS, связанный с сокетом, был изменен.
  2. После вызова LPWSPIoctl с SIO_GET_QOS при изменении QOS.

FD_GROUP_QOS

Зарезервировано для будущего использования с группами сокетов:

  1. При вызове LPWSPAsyncSelect , если группа QOS, связанная с сокетом, была изменена.
  2. После вызова LPWSPIoctl с SIO_GET_GROUP_QOS при изменении QOS группы.

FD_ROUTING_INTERFACE_CHANGE

  1. после вызова LPWSPIoctl с SIO_ROUTING_INTERFACE_CHANGE при изменении локального интерфейса, который должен использоваться для достижения назначения, указанного в IOCTL.

FD_ADDRESS_LIST_CHANGE

  1. после вызова LPWSPIoctl с SIO_ADDRESS_LIST_CHANGE при изменении списка локальных адресов, к которым может привязаться клиент SPI сокетов Windows.

Требования

Требование Значение
Минимальная версия клиента сборка Windows 10 20348
Минимальная версия сервера сборка Windows 10 20348
Верхняя часть ws2spi.h

См. также раздел

Функция обратного вызова LPWSPAsyncSelect