LPFN_RIORECEIVEEX回调函数 (mswsock.h)
RIOReceiveEx 函数接收连接的已注册 I/O TCP 套接字或绑定的已注册 I/O UDP 套接字上的网络数据,该套接字具有用于 Winsock 注册的 I/O 扩展的其他选项。
语法
LPFN_RIORECEIVEEX LpfnRioreceiveex;
int LpfnRioreceiveex(
RIO_RQ SocketQueue,
PRIO_BUF pData,
ULONG DataBufferCount,
PRIO_BUF pLocalAddress,
PRIO_BUF pRemoteAddress,
PRIO_BUF pControlContext,
PRIO_BUF pFlags,
DWORD Flags,
PVOID RequestContext
)
{...}
参数
SocketQueue
标识连接的已注册 I/O UDP 套接字或绑定的已注册 I/O UDP 套接字的描述符。
pData
用于接收数据的已注册缓冲区部分的说明。
如果应用程序不需要在 UDP 数据报中接收数据有效负载,则对于绑定注册的 I/O UDP 套接字,此参数可能为 NULL。
DataBufferCount
一个数据缓冲区计数参数,指示是否在 pData 参数指向的缓冲区中接收数据。
如果 pData 为 NULL,则此参数应设置为零。 否则,此参数应设置为 1。
pLocalAddress
缓冲区段在完成时将保存接收网络数据的本地地址。
如果应用程序不希望接收本地地址,则此参数可能为 NULL 。 如果此参数不为 NULL,则缓冲区段必须至少为 SOCKADDR_INET 结构的大小。
pRemoteAddress
一个缓冲区段,完成后将保存从中接收网络数据的远程地址。
如果应用程序不希望接收远程地址,则此参数可能为 NULL 。 如果此参数不为 NULL,则缓冲区段必须至少为 SOCKADDR_INET 结构的大小。
pControlContext
一个缓冲区切片,完成后将保存有关接收操作的其他控制信息。
如果应用程序不想接收其他控件信息,则此参数可能为 NULL 。
pFlags
Flags
一组标志,用于修改 RIOReceiveEx 函数的行为。
Flags 参数可以包含以下选项的组合,这些选项在Mswsockdef.h
头文件中定义:
RIO_MSG_COMMIT_ONLY
将提交以前使用 RIO_MSG_DEFER 标志添加的请求。
设置 RIO_MSG_COMMIT_ONLY 标志时,不能指定其他标志。 设置RIO_MSG_COMMIT_ONLY标志后,pData、pLocalAddress、pRemoteAddress、pControlContext、pFlags 和 RequestContext 参数必须为 NULL,DataBufferCount 参数必须为零。
在设置了 RIO_MSG_DEFER 标志的情况下发出多个请求后,通常偶尔会使用此标志。 这样就无需使用 RIO_MSG_DEFER 标志在没有 RIO_MSG_DEFER 标志的情况下发出最后一个请求,从而导致最后一个请求的完成速度比其他请求慢得多。
与对 RIOReceiveEx 函数的其他调用不同,当 RIO_MSG_COMMIT_ONLY 标志设置为时,不需要序列化 对 RIOReceiveEx 函数的调用。 对于单个RIO_RQ,可以在一个线程上使用 RIO_MSG_COMMIT_ONLY 调用 RIOReceiveEx 函数,同时在另一个线程上调用 RIOReceiveEx 函数。
RIO_MSG_DONT_NOTIFY
当请求完成插入到其完成队列时,请求不应触发 RIONotify 函数。
RIO_MSG_DEFER
不需要立即执行请求。 这会将请求插入请求队列,但它可能会触发或不触发请求的执行。
数据接收可能会延迟,直到在未设置RIO_MSG_DEFER标志的情况下,在 SocketQueue 参数中传递RIO_RQ发出接收请求。 若要触发请求队列中所有接收的执行,请在不设置RIO_MSG_DEFER标志的情况下调用 RIOReceive 或 RIOReceiveEx 函数。
注意
无论是否设置了RIO_MSG_DEFER,接收请求都会根据 SocketQueue 参数中传递的RIO_RQ上的未完成 I/O 容量收费。
RIO_MSG_WAITALL
在发生以下事件之一之前, RIOReceiveEx 函数不会完成:
- 调用方在 pData 参数中提供的缓冲区切片已完全满。
- 该连接已关闭。
- 请求已取消或发生错误。
数据报套接字或面向消息的无连接套接字不支持此标志。
RequestContext
要与此接收操作关联的请求上下文。
返回值
如果未发生错误, RIOReceiveEx 函数将返回 TRUE。 在这种情况下,接收操作已成功启动,完成操作已排队或操作已成功启动,完成将在以后排队。
值为 FALSE 表示函数失败,操作未成功启动,并且不会将完成指示排入队列。 可以通过调用 WSAGetLastError 函数来检索特定的错误代码。
返回代码 | 说明 |
---|---|
WSAEFAULT | 系统尝试在调用中使用指针参数时检测到指针地址无效。 如果在将操作排队或调用之前,为参数中传递的任何 RIO_BUF 结构释放缓冲区标识符或释放缓冲区,则返回此错误。 |
WSAEINVAL | 向该函数传递了无效参数。 如果 SocketQueue 参数无效、 dwFlags 参数包含的值对接收操作无效,或者完成队列的完整性受到损害,则返回此错误。 对于参数的其他问题,也可能会返回此错误。 |
WSAENOBUFS | 无法分配足够的内存。 如果与 SocketQueue 参数关联的 I/O 完成队列已满,或者 I/O 完成队列是使用零个接收条目创建的,则返回此错误。 |
WSA_OPERATION_ABORTED | 在接收操作处于挂起状态时,操作已取消。 如果在本地或远程关闭套接字,或者执行 WSAIoctl 中的 SIO_FLUSH 命令,则返回此错误。 |
注解
应用程序可以使用 RIOReceiveEx 函数将网络数据接收到完全包含在单个已注册缓冲区中的任何缓冲区中。 pData 参数指向的 RIO_BUF 结构的 Offset 和 Length 成员确定在缓冲区中接收网络数据的位置。
调用 RIOReceiveEx 函数后,在 pData 参数中传递的缓冲区(包括 RIO_BUF 结构的 BufferId 成员中的 RIO_BUFFERID )在接收操作期间必须保持有效。
为了避免争用条件,不应在请求完成之前读取或写入与接收请求关联的缓冲区。 这包括使用缓冲区作为发送请求的源或另一个接收请求的目标。 不与任何接收请求关联的已注册缓冲区部分不包括在此限制中。
pLocalAddress 参数可用于检索接收数据的本地地址。 pRemoteAddress 参数可用于检索从中接收数据的远程地址。 本地地址和远程地址作为 SOCKADDR_INET 结构返回。 因此,pLocalAddress 或 pRemoteAddress 参数指向的RIO_BUF的 Length 成员应等于或大于SOCKADDR_INET结构的大小。
下表总结了可用于 pControlContext 成员中的控件信息的控件数据的各种用途。
协议 | cmsg_level | cmsg_type | 说明 |
---|---|---|---|
IPv4 | IPPROTO_IP | IP_ORIGINAL_ARRIVAL_IF | 接收原始 IPv4 到达接口,其中为数据报套接字接收了数据包。 当 Teredo、6to4 或 ISATAP 隧道用于 IPv4 NAT 遍历时,防火墙将使用此控制数据。 cmsg_data[] 成员是包含 ifdef.h 头文件中定义的IF_INDEX的 ULONG。 有关详细信息,请参阅 IP_ORIGINAL_ARRIVAL_IF 套接字选项的 IPPROTO_IP 套接字选项。 |
IPv4 | IPPROTO_IP | IP_PKTINFO | 指定/接收数据包信息。 有关详细信息,请参阅 IP_PKTINFO 套接字选项 的 IPPROTO_IP 套接字选项。 |
IPv6 | IPPROTO_IPV6 | IPV6_DSTOPTS | 指定/接收目标选项。 |
IPv6 | IPPROTO_IPV6 | IPV6_HOPLIMIT | 指定/接收跃点限制。 有关详细信息,请参阅 IPV6_HOPLIMIT 套接字选项 的 IPPROTO_IPV6 套接字选项。 |
IPv6 | IPPROTO_IPV6 | IPV6_HOPOPTS | 指定/接收逐跃点选项。 |
IPv6 | IPPROTO_IPV6 | IPV6_NEXTHOP | 指定下一跃点地址。 |
IPv6 | IPPROTO_IPV6 | IPV6_PKTINFO | 指定/接收数据包信息。 有关详细信息,请参阅 IPV6_PKTINFO 套接字选项的 IPPROTO_IPV6 套接字选项。 |
IPv6 | IPPROTO_IPV6 | IPV6_RTHDR | 指定/接收路由标头。 |
控制数据由一个或多个控件数据对象组成,每个对象都以 WSACMSGHDR 结构开头,定义如下:
} WSACMSGHDR;
WSACMSGHDR 结构的成员如下所示:
术语 | 说明 |
---|---|
cmsg_len | 从 WSACMSGHDR 开头到数据末尾的数据字节数 (不包括可能遵循数据) 的填充字节。 |
cmsg_level | 发起控件信息的协议。 |
cmsg_type | 特定于协议的控件信息类型。 |
Flags 参数可用于影响 RIOReceiveEx 函数调用的行为,超出为关联套接字指定的选项。 此函数的行为由与 SocketQueue 参数关联的套接字上设置的任何套接字选项和 Flags 参数中指定的值的组合决定。
注意
必须在运行时通过调用 WSAIoctl 函数并指定SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER操作码来获取指向 RIOReceiveEx 函数的函数指针。 传递给 WSAIoctl 函数的输入缓冲区必须包含 WSAID_MULTIPLE_RIO,这是一个全局唯一标识符 (GUID) 其值标识 Winsock 注册的 I/O 扩展函数。 成功后, WSAIoctl 函数返回的输出包含指向 RIO_EXTENSION_FUNCTION_TABLE 结构的指针,该结构包含指向 Winsock 注册的 I/O 扩展函数的指针。 SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER IOCTL 在 Ws2def.h 头文件中定义。 WSAID_MULTIPLE_RIO GUID 在 Mswsock.h 头文件中定义。
Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。
Windows 8.1和Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。
要求
要求 | 值 |
---|---|
Header | mswsock.h |