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) 客户端感兴趣的网络事件的组合的 Bitmask。 使用带上述任何值的按位 OR 运算符构造。
价值 | 意义 |
---|---|
|
有关阅读准备情况的通知。 |
|
写入准备情况通知的问题。 |
|
发出 OOB 数据的到达通知。 |
|
发出传入连接的通知。 |
|
已完成连接的问题通知。 |
|
发出套接字关闭通知。 |
|
发出套接字服务质量(QoS)更改通知。 |
|
保留。 |
|
指定目标的路由接口更改通知。 |
|
套接字协议系列的本地地址列表更改通知。 |
[out] lpErrno
指向错误代码的指针。 有关详细信息,请参阅 返回值 部分。
返回值
如果 Windows Sockets SPI 客户端对网络事件集感兴趣的声明成功,则返回值为零。 否则,返回值SOCKET_ERROR,lpErrno中提供了特定的错误代码。
错误代码 | 意义 |
---|---|
网络子系统已失败。 | |
指示指定参数之一无效,例如不引用现有窗口的窗口句柄,或者指定的套接字处于无效状态。 | |
正在阻止 Windows 套接字调用,或者服务提供商仍在处理回调函数。 | |
描述符不是套接字。 |
请参阅 备注,了解可在应用程序窗口收到消息时设置的其他错误代码(在消息中 lParam 的高字)。
言论
每当服务提供商检测到由 lEvent 参数指定的任何网络事件时,此函数用于请求服务提供商将 Windows 消息发送到客户端的窗口 hWnd。 服务提供商应使用 WPUPostMessage 函数发布消息。 要发送的消息由 wMsg 参数指定。 标识需要通知的套接字。
无论 lEvent
为套接字调用 LPWSPAsyncSelect 会取消以前任何 LPWSPAsyncSelect 或 同一套接字的 LPWSPEventSelect。 例如,若要接收读取和写入通知,Windows Sockets SPI 客户端必须调用 LPWSPAsyncSelect,FD_READ和FD_WRITE,如下所示。
rc = WSPAsyncSelect(s, hWnd, wMsg, FD_READ | FD_WRITE, &error);
无法为不同的事件指定不同的消息。 以下代码不起作用;第二个调用取消第一个调用的效果,唯一的关联将是与 wMsg2 关联的FD_WRITE事件。
// Incorrect example.
rc = WSPAsyncSelect(s, hWnd, wMsg1, FD_READ, &error);
rc = WSPAsyncSelect(s, hWnd, wMsg2, FD_WRITE, &error);
若要取消所有通知(即,若要指示服务提供商不应发送与套接字上的网络事件相关的其他消息),请将 lEvent 设置为零。
rc = WSPAsyncSelect(s, hWnd, 0, 0, &error);
由于 LPWSPAccept“ed 套接字具有与用于接受它的侦听套接字相同的属性,因此为侦听套接字设置的任何 LPWSPAsyncSelect 事件都应用于接受的套接字。 例如,如果侦听套接字具有 LPWSPAsyncSelect 事件FD_ACCEPT、FD_READ和FD_WRITE,则该侦听套接字上接受的任何套接字也将具有用于消息的相同 wMsg 值的FD_ACCEPT、FD_READ和FD_WRITE事件。 如果需要其他 wMsg 或事件,则 Windows 套接字 SPI 客户端应调用 LPWSPAsyncSelect、传递接受的套接字以及所需的新信息。
当指定套接字 上发生指定网络事件之一时,服务提供商使用 WPUPostMessage 将消息 wMsg 发送到 Windows Sockets SPI 客户端的窗口 hWnd。 在发布的消息中,wParam 参数标识发生网络事件的套接字。 lParam 的低字指定已发生的网络事件。 可能指示的网络事件代码如下所示。
价值 | 意义 |
---|---|
FD_READ | 套接字 已准备好进行读取 |
FD_WRITE | 套接字 已准备好编写 |
FD_OOB | 带外数据已准备好在套接字 上读取 |
FD_ACCEPT | 套接字 已准备好接受新的传入连接 |
FD_CONNECT | 在套接字 上启动的连接已完成 |
FD_CLOSE | 套接字 标识的连接已关闭 |
FD_QOS | 与套接字 关联的服务质量已更改 |
FD_GROUP_QOS | 保留以供将来与套接字组一起使用:与套接字组关联的服务质量已更改 所属的套接字组 |
FD_ROUTING_INTERFACE_CHANGE | 应用于发送到指定目标的本地接口已更改 |
FD_ADDRESS_LIST_CHANGE | Windows Sockets SPI 客户端可绑定到的套接字协议系列的地址列表已更改 |
lParam 的高字包含任何错误代码(可以使用 WSAGETSELECTERROR 宏提取)。 错误代码是 ws2spi.h
中定义的任何错误。 下表列出了每个网络事件的可能错误代码。
事件:FD_CONNECT
错误代码 | 意义 |
---|---|
指定系列中的地址不能用于此套接字。 | |
尝试连接被拒绝。 | |
此时无法从此主机访问网络。 | |
namelen 参数无效。 | |
套接字已绑定到地址。 | |
套接字已连接。 | |
不再提供文件描述符。 | |
没有可用的缓冲区空间。 无法连接套接字。 | |
套接字未连接。 | |
尝试连接超时而不建立连接。 |
事件:FD_CLOSE
错误代码 | 意义 |
---|---|
网络子系统失败。 | |
连接已由远程端重置。 | |
由于超时或其他故障,连接已终止。 |
事件...:FD_ACCEPT、FD_ADDRESS_LIST_CHANGE、FD_GROUP_QOS、FD_OOB、FD_QOS、FD_READ、FD_WRITE
错误代码 | 意义 |
---|---|
网络子系统失败。 |
事件:FD_ROUTING_INTERFACE_CHANGE
错误代码 | 意义 |
---|---|
指定的目标不再可访问。 | |
网络子系统失败。 |
尽管可以调用 LPWSPAsyncSelect,但对多个事件感兴趣,但服务提供商会为每个事件发出相同的 Windows 消息。
Windows 套接字 2 提供程序不应持续向 Windows Sockets SPI 客户端填充特定网络事件的消息。 成功将特定事件的通知发布到 Windows Sockets SPI 客户端窗口后,该网络事件的进一步消息不会发布到 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 | 没有 |
FD_CLOSE | 没有 |
FD_QOS | 使用 SIO_GET_QOS LPWSPIoctl |
FD_GROUP_QOS | 保留用于套接字组的未来用途:LPWSPIoctl 与 SIO_GET_GROUP_QOS |
FD_ROUTING_INTERFACE_CHANGE | 使用命令SIO_ROUTING_INTERFACE_CHANGE LPWSPIoctl |
FD_ADDRESS_LIST_CHANGE | 使用命令SIO_ADDRESS_LIST_CHANGE LPWSPIoctl |
对重新启用例程的任何调用(即使是失败的例程)都会导致重新启用相关事件的消息发布。
对于FD_READ、FD_OOB和FD_ACCEPT事件,消息发布 级别触发。 这意味着,如果调用重新启用例程,并且调用后仍满足相关条件,则会将 LPWSPAsyncSelect 消息发布到 Windows Sockets SPI 客户端。
FD_QOS和FD_GROUP_QOS事件被视为 边缘触发。 当发生 QOS 更改时,将恰好发布一次消息。 在提供程序检测到 QOS 中的进一步更改或 Windows 套接字 SPI 客户端重新协商套接字的 QOS 之前,不会发出进一步的消息。
FD_ROUTING_INTERFACE_CHANGE和FD_ADDRESS_LIST_CHANGE事件也被视为 边缘触发。 当 Windows 套接字 SPI 客户端通过发出 WSAIoctl 并相应地发出SIO_ROUTING_INTERFACE_CHANGE或SIO_ADDRESS_LIST_CHANGE来请求通知后,将恰好发布一次消息。 在 Windows 套接字 SPI 客户端重新发出 IOCTL 并检测到另一个更改之前,不会发出进一步消息, 检测到另一个更改。
如果 Windows Sockets SPI 客户端调用 LPWSPAsyncSelect或调用重新启用函数时发生任何事件,则会相应地发布消息。 例如,请考虑以下序列。
- Windows 套接字 SPI 客户端调用 LPWSPListen。
- 收到连接请求,但尚未接受。
- Windows Sockets SPI 客户端 LPWSPAsyncSelect 指定它想要接收套接字的FD_ACCEPT消息。 由于事件的持久性,WinSock 服务提供商会立即发布FD_ACCEPT消息。
FD_WRITE事件处理方式略有不同。 当套接字首次连接到 LPWSPConnect(FD_CONNECT之后)时,将发布FD_WRITE消息 如果还已注册)或接受 LPWSPAccept,然后在 LPWSPSend 或 LPWSPSendTo 失败,WSAEWOULDBLOCK 和缓冲区空间变为可用。 因此,Windows 套接字 SPI 客户端可以假定从第一条FD_WRITE消息开始发送,直到发送返回 WSAEWOULDBLOCK 为止。 发生此类故障后,Windows Sockets SPI 客户端将收到通知,该客户端可以使用FD_WRITE消息再次发送。
仅当套接字配置为单独接收带外数据时,才会使用FD_OOB事件。 如果套接字配置为内联接收带外数据,则带外(加速)数据被视为正常数据,并且 Windows Sockets SPI 客户端必须注册对FD_READ事件的兴趣,而不是FD_OOB事件。
FD_CLOSE消息中的错误代码指示套接字关闭是正常还是中止。 如果错误代码为 0,则关闭操作正常;如果错误代码为 WSAECONNRESET,则重置套接字的虚拟线路。 这仅适用于面向连接的套接字,例如SOCK_STREAM。
当收到对应于套接字的虚拟线路的关闭指示时,将发布FD_CLOSE消息。 在 TCP 术语中,这意味着当连接进入 TIME WAIT 或 CLOSE WAIT 状态时,将发布FD_CLOSE。 这会导致远程端在发送端或 LPWSPCloseSocket上执行 LPWSPShutdown。 只有在从套接字读取所有数据后才会发布FD_CLOSE是正确的。
在正常关闭的情况下,服务提供商应发送一条FD_CLOSE消息,以指示仅在读取所有收到的数据后才关闭虚拟线路。 它不应发送FD_READ消息来指示此条件。
当流规范中与套接字 关联的任何字段发生更改或 所属的套接字组时,将发布FD_QOS或FD_GROUP_QOS消息。 服务提供商必须使用SIO_GET_QOS和/或SIO_GET_GROUP_QOS通过 LPWSPIoctl 更新客户端可用的 QOS 信息。
发布FD_ROUTING_INTERFACE_CHANGE消息时,应使用本地接口访问
发布FD_ADDRESS_LIST_CHANGE消息时,Windows 套接字 SPI 客户端在发出 SIO_ADDRESS_LIST_CHANGE
下面是每个异步通知消息的事件和条件的摘要。
FD_READ
- 调用 LPWSPAsyncSelect 时,如果当前有数据可供接收。
- 数据到达时,如果尚未发布FD_READ。
- 调用 LPWSPRecv 或 LPWSPRecvFrom(无论是否具有MSG_PEEK),如果数据仍可供接收。
启用 LPWSPSetSockOpt SO_OOBINLINE 时,数据 包括上述实例中的正常数据和带外数据(OOB)。
FD_WRITE
- 调用 LPWSPAsyncSelect 时,如果 LPWSPSend 或 LPWSPSendTo。
建立连接时, LPWSPConnect 或LPWSPAccept 后调用。- LPWSPSend 或 LPWSPSendTo WSAEWOULDBLOCK 失败后,LPWSPSend 或 LPWSPSendTo 可能会成功。
- 在无连接套接字上 LPWSPBind 后。 FD_WRITE此时可能发生或可能不会发生(依赖于实现)。 在任何情况下,LPWSPBind后,始终可以立即写入无连接套接字。
FD_OOB(仅在禁用 LPWSPSetSockOpt SO_OOBINLINE 时有效(默认值)
- 当调用 LPWSPAsyncSelect 时,如果有 OOB 数据当前可以使用 MSG_OOB 标志接收。
- 当 OOB 数据到达时,如果尚未发布FD_OOB。
- 在 LPWSPRecv 或 LPWSPRecvFrom 后,如果 OOB 数据仍可供接收,则调用或不使用MSG_OOB标志。
FD_ACCEPT
- 当调用 LPWSPAsyncSelect 时,如果当前有可供接受的连接请求。
- 当连接请求到达时,如果尚未发布FD_ACCEPT。
- 调用 LPWSPAccept 后,如果有另一个连接请求可供接受。
FD_CONNECT
- 调用 LPWSPAsyncSelect 时,如果当前已建立连接。
- 调用 LPWSPConnect 后,建立连接时(即使 LPWSPConnect 立即成功(与数据报套接字一样,即使立即失败)。
- 调用 WSPJoinLeaf 后,联接操作完成。
- 连接后,WSAConnect或 WSPJoinLeaf 使用非阻塞的、面向连接的套接字调用。 初始操作返回时出现 WSAEWOULDBLOCK 的特定错误,但网络操作继续进行。 在确定结果后,操作最终是否成功,FD_CONNECT发生。 客户端应检查错误代码,以确定结果是成功还是失败。
FD_CLOSE(仅适用于面向连接的套接字(例如,SOCK_STREAM))
- 调用 LPWSPAsyncSelect 时,如果套接字连接已关闭。
- 远程系统启动正常关闭后,当当前没有数据可供接收(如果已收到数据并在远程系统启动正常关闭时等待读取),则在读取所有挂起的数据之前不会传送FD_CLOSE。
- 本地系统启动正常关闭后,LPWSPShutdown,远程系统已响应 数据结束 通知(如 TCP FIN),目前无法接收任何数据。
- 当远程系统中止连接(例如发送的 TCP RST),lParam 将包含 WSAECONNRESET 错误值。
调用 LPWSPCloseSocket 后,不会发布FD_CLOSE。
FD_QOS
- 调用 LPWSPAsyncSelect 时,如果已更改与套接字关联的 QOS。
- 调用具有SIO_GET_QOS的 LPWSPIoctl
LPWSPIoctl 后,将更改 QOS。
FD_GROUP_QOS
保留以供将来用于套接字组:
- 调用 LPWSPAsyncSelect 时,如果已更改与套接字关联的组 QOS。
- 调用 LPWSPIoctl 并调用SIO_GET_GROUP_QOS后,将更改组 QOS。
FD_ROUTING_INTERFACE_CHANGE
- 调用 LPWSPIoctl 并调用SIO_ROUTING_INTERFACE_CHANGE后,应使用本地接口访问 IOCTL 中指定的目标。
FD_ADDRESS_LIST_CHANGE
- 调用 SIO_ADDRESS_LIST_CHANGE LPWSPIoctl 后,Windows Sockets SPI 客户端可以绑定更改的本地地址列表。
要求
要求 | 价值 |
---|---|
最低支持的客户端 | Windows 10 内部版本 20348 |
支持的最低服务器 | Windows 10 内部版本 20348 |
标头 | ws2spi.h |