LPFN_WSARECVMSG回调函数 (mswsock.h)
LPFN_WSARECVMSG 是函数指针类型。 在应用中实现匹配的 WSARecvMsg 回调函数。 系统使用回调函数通过连接的套接字将内存中数据或文件数据传输到你。
WSARecvMsg 回调函数从已连接和未连接的套接字接收带有消息的辅助数据/控制信息。
注意
此函数是 Windows 套接字规范中特定于 Microsoft 的扩展。
语法
LPFN_WSARECVMSG LpfnWsarecvmsg;
INT LpfnWsarecvmsg(
SOCKET s,
LPWSAMSG lpMsg,
LPDWORD lpdwNumberOfBytesRecvd,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
{...}
参数
s
类型:_In_ SOCKET
标识套接字的描述符。
lpMsg
类型:_Inout_ LPWSAMSG
指向基于 msghdr 结构的 Posix.1g 规范的 WSAMSG 结构的指针。
lpdwNumberOfBytesRecvd
类型:_Out_opt_ LPDWORD
指向 DWORD 的指针,其中包含此调用接收的字节数(如果 WSARecvMsg 操作立即完成)。
为了避免潜在的错误结果,如果 lpOverlapped 参数不是 NULL,请为此参数传递 NULL。 仅当 lpOverlapped 参数不为 NULL 时,此参数才能为 NULL。
lpOverlapped
类型:_Inout_opt_ LPWSAOVERLAPPED
指向 WSAOVERLAPPED 结构的指针。 对于非重叠结构,被忽略。
lpCompletionRoutine
类型:_In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
指向完成接收操作时调用的完成例程的指针。 对于非重叠结构,被忽略。
返回值
如果未发生任何错误,并且接收操作已立即完成, 则 WSARecvMsg 返回零。 在这种情况下,一旦调用线程处于可警报状态,就已计划调用完成例程。 否则,将返回值 SOCKET_ERROR,并且可以通过调用 WSAGetLastError 检索特定的错误代码。 错误代码 WSA_IO_PENDING 指示重叠操作已成功启动,稍后将指示完成。
任何其他错误代码指示操作未成功启动,如果请求了重叠的操作,将不会发生完成指示。
错误代码 | 含义 |
---|---|
WSAECONNRESET | 对于 UDP 数据报套接字,此错误将指示以前的发送操作导致 ICMP“端口无法访问”消息。 |
WSAEFAULT | lpBuffers、lpFlags、lpFrom、lpNumberOfBytesRecvd、lpFromlen、lpOverlapped 或 lpCompletionRoutine 参数未完全包含在用户地址空间的有效部分:lpFrom 缓冲区太小,无法容纳对等地址。 如果 lpMsg 参数指向的 WSAMSG 结构的名称成员是 NULL 指针,并且 WSAMSG 结构的 namelen 成员未设置为零,则也会返回此错误。 如果 lpMsg 参数指向的 WSAMSG 结构的 Control.buf 成员是 NULL 指针,并且 WSAMSG 结构的 Control.len 成员未设置为零,则也会返回此错误。 |
WSAEINPROGRESS | 阻止 Windows 套接字 1.1 调用正在进行,或者服务提供商仍在处理回调函数。 |
WSAEINTR | 阻止的 Windows 套接字 1.1 调用已通过 WSACancelBlockingCall 取消。 |
WSAEINVAL | 套接字尚未 (绑定,例如) 。 |
WSAEMSGSIZE | 消息太大,无法放入指定的缓冲区,对于不可靠的协议, (仅) 不符合缓冲区的消息的任何尾随部分被丢弃。 |
WSAENETDOWN | 网络子系统发生故障。 |
WSAENETRESET | 对于数据报套接字,此错误显示生存时间已经过期。 |
WSAENOTCONN | 仅) (面向连接的套接字未连接套接字。 |
WSAETIMEDOUT | 套接字超时。如果套接字使用 SO_RCVTIMEO 套接字选项指定了等待超时,并且已超出超时,则返回此错误。 |
WSAEOPNOTSUPP | 不支持套接字操作。 如果 lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员包含非数据报套接字上的 MSG_PEEK 控件标志,则返回此错误。 |
WSAEWOULDBLOCK | Windows NT: 重叠套接字:存在过多未完成的重叠 I/O 请求。 非重叠套接字:套接字标记为非阻止,接收操作无法立即完成。 |
WSANOTINITIALIZED | 在使用此函数之前,必须成功调用 WSAStartup 。 |
WSA_IO_PENDING | 已成功启动重叠操作,稍后将指示完成。 |
WSA_OPERATION_ABORTED | 由于套接字关闭,重叠的操作已取消。 |
注解
WSARecvMsg 函数可以代替 WSARecv 和 WSARecvFrom 函数,以接收来自已连接和未连接的套接字的数据和可选控制信息。 WSARecvMsg 函数只能与数据报和原始套接字一起使用。 必须打开 s 参数中的套接字描述符,并将套接字类型设置为 SOCK_DGRAM 或 SOCK_RAW。
注意必须在运行时通过调用 WSAIoctl 函数并指定SIO_GET_EXTENSION_FUNCTION_POINTER操作码来获取 WSARecvMsg 函数的函数指针。 传递给 WSAIoctl 函数的输入缓冲区必须包含 WSAID_WSARECVMSG,这是一个全局唯一标识符 (GUID) 其值标识 WSARecvMsg 扩展函数。 成功后, WSAIoctl 函数返回的输出包含指向 WSARecvMsg 函数的指针。 WSAID_WSARECVMSG GUID 在 Mswsock.h 头文件中定义。
lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员只能包含输入上的 MSG_PEEK 控件标志。
重叠套接字是使用 WSASocket 函数调用创建的,该调用设置了 WSA_FLAG_OVERLAPPED 标志。 对于重叠套接字,除非 lpOverlapped 和 lpCompletionRoutine 参数均为 NULL,否则接收信息将使用重叠的 I/O。 当 lpOverlapped 和 lpCompletionRoutine 参数均为 NULL 时,套接字被视为非重叠套接字。
完成指示与重叠的套接字一起发生。 传输使用缓冲区或缓冲区后,将触发完成例程或设置事件对象。 如果操作未立即完成,则通过完成例程或通过调用 WSAGetOverlappedResult 函数检索最终完成状态。
对于重叠套接字, WSARecvMsg 用于发布一个或多个缓冲区,传入数据变为可用时将放入其中,之后应用程序指定的完成指示 (调用完成例程或事件对象的设置) 。 如果操作未立即完成,则通过完成例程或 WSAGetOverlappedResult 函数检索最终完成状态。
对于非重叠套接字,阻塞语义与标准 recv 函数的语义相同,并且 忽略 lpOverlapped 和 lpCompletionRoutine 参数。 传输已接收和缓冲的任何数据都将复制到指定的用户缓冲区中。 如果传输当前没有接收和缓冲数据的阻塞套接字,则调用将阻止,直到收到数据。 Windows 套接字 2 未为此函数定义任何标准阻止超时机制。 对于充当字节流协议的协议,堆栈会尝试根据可用缓冲区空间和可用接收的数据量返回尽可能多的数据。 但是,接收单个字节足以取消阻止调用方。 不能保证返回的字节超过一个字节。 对于充当面向消息的协议,需要完整消息来取消阻止调用方。
注意SO_RCVTIMEO套接字选项仅适用于阻止套接字。
缓冲区按 lpMsg 参数指向的 WSAMSG 结构的 lpBuffers 成员所指向的数组中的出现顺序填充,缓冲区将被打包,以便不创建任何孔。
如果此函数以重叠方式完成,则 Winsock 服务提供商负责在从此调用返回之前捕获此 WSABUF 结构。 这使应用程序能够生成由 lpMsg 参数指向的 WSAMSG 结构的 lpBuffers 成员所指向的基于堆栈的 WSABUF 数组。
对于面向消息的套接字 (SOCK_DGRAM 或 SOCK_RAW) 的套接字类型,传入消息将放入缓冲区中,最大大小为缓冲区的总大小,重叠套接字会出现完成指示。 如果消息大于缓冲区,则缓冲区中会填充消息的第一部分,并丢失多余的数据, WSARecvMsg 将生成错误 WSAEMSGSIZE。
在 SOCK_DGRAM或 SOCK_RAW 类型的 IPv4 套接字上启用 IP_PKTINFO 套接字选项时,WSARecvMsg 函数将在 lpMsg 参数指向的 WSAMSG 结构中返回数据包信息。 返回的 WSAMSG 结构中的控制数据对象之一将包含用于存储接收的数据包地址信息的 in_pktinfo 结构。
对于通过 IPv4 接收的数据报,收到的 WSAMSG 结构的 Control 成员将包含包含 WSACMSGHDR 结构的 WSABUF 结构。 此 WSACMSGHDR 结构的cmsg_level成员将包含IPPROTO_IP,此结构的cmsg_type成员将包含IP_PKTINFO,cmsg_data成员将包含用于存储收到的 IPv4 数据包地址信息的in_pktinfo结构。 in_pktinfo结构中的 IPv4 地址是从中接收数据包的 IPv4 地址。
在 SOCK_DGRAM或 SOCK_RAW 类型的 IPv6 套接字上启用 IPV6_PKTINFO 套接字选项时,WSARecvMsg 函数将在 lpMsg 参数指向的 WSAMSG 结构中返回数据包信息。 返回的 WSAMSG 结构中的控制数据对象之一将包含用于存储接收的数据包地址信息的 in6_pktinfo 结构。
对于通过 IPv6 接收的数据报,收到的 WSAMSG 结构的 Control 成员将包含包含 WSACMSGHDR 结构的 WSABUF 结构。 此 WSACMSGHDR 结构的cmsg_level成员将包含IPPROTO_IPV6,此结构的cmsg_type成员将包含IPV6_PKTINFO,cmsg_data成员将包含用于存储收到的 IPv6 数据包地址信息的in6_pktinfo结构。 in6_pktinfo结构中的 IPv6 地址是从中接收数据包的 IPv6 地址。
对于双堆栈数据报套接字,如果应用程序要求 WSARecvMsg 函数在 WSAMSG 结构中返回通过 IPv4 接收的数据报的数据包信息,则必须在套接字上将 IP_PKTINFO 套接字选项设置为 true。 如果在套接字上仅将 IPV6_PKTINFO 选项设置为 true,则将为通过 IPv6 接收的数据报提供数据包信息,但可能不会为通过 IPv4 接收的数据报提供数据包信息。
请注意, Ws2ipdef.h 头文件自动包含在 Ws2tcpip.h 中,不应直接使用。
注意 当给定线程退出时,将取消由该线程发起的所有 I/O。 对于重叠的套接字,如果在操作完成之前关闭线程,挂起的异步操作可能会失败。 有关详细信息,请参阅 ExitThread。
Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。
Windows 8.1和Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。
dwFlags
输入时,lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员可用于影响函数调用的行为,超出为关联的套接字指定的套接字选项。 也就是说,此函数的语义由 WSAMSG 结构的套接字选项和 dwFlags 成员决定。 lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员的唯一可能的输入值是MSG_PEEK。
值 | 含义 |
---|---|
MSG_PEEK | :速览传入数据。 数据将复制到缓冲区中,但不会从输入队列中删除。 此标志仅对非重叠套接字有效。 |
输入时 dwFlags 成员的可能值在 Winsock2.h 头文件中定义。
在输出时,lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员可能会返回以下任意值的组合。
值 | 含义 |
---|---|
MSG_BCAST | 数据报以链接层广播的形式接收,或者接收了作为广播地址的目标 IP 地址。 |
MSG_CTRUNC | 控件 (辅助) 数据被截断。 存在的控制数据多于为其分配的空间的进程。 |
MSG_MCAST | 接收数据报时的目标 IP 地址是多播地址。 |
MSG_TRUNC | 数据报被截断。 存在的数据多于进程为其分配的空间。 |
在为 Windows Vista 及更高版本发布的 Microsoft Windows 软件开发工具包 (Windows SDK) (SDK) 上,头文件的组织已更改,并且输出中 dwFlags 成员的可能值在 Ws2def.h 头文件中定义,Ws2def.h 头文件自动包含在其中。
在适用于 Windows Server 2003 及更早版本的平台软件开发工具包 (SDK) 上,输出中 dwFlags 成员的可能值在 Mswsock.h 头文件中定义。
注意当在 lpOverlapped 参数设置为 NULL 的情况下发出阻止的 Winsock 调用(例如 WSARecvMsg)时,Winsock 可能需要等待网络事件才能完成调用。 在这种情况下,Winsock 执行可发出警报的等待, (在同一线程上计划的 APC) 异步过程调用可能会中断该等待。 在 APC 内发出另一个阻止 Winsock 调用,该调用中断了同一线程上正在进行的阻止 Winsock 调用将导致未定义的行为,并且 Winsock 客户端绝不能尝试。
重叠套接字 I/O
如果重叠操作立即完成, WSARecvMsg 将返回值零, lpNumberOfBytesRecvd 参数将更新为接收的字节数, lpFlags 参数指示的标志位也会更新。 如果已成功启动重叠操作并将稍后完成, 则 WSARecvMsg 将返回 SOCKET_ERROR 并指示 错误代码WSA_IO_PENDING。 在这种情况下,不会更新 lpNumberOfBytesRecvd 。 重叠操作完成后,通过完成例程中的 cbTransferred 参数(如果指定 () )或通过 WSAGetOverlappedResult 中的 lcbTransferred 参数指示传输的数据量。 标志值是通过检查 WSAGetOverlappedResult 的 lpdwFlags 参数获取的。
可以从以前的 WSARecv、WSARecvFrom、WSARecvMsg、WSARecvMsg、WSASend、WSASendMsg 或 WSASendTo 函数的完成例程中调用使用重叠 I/O 的 WSARecvMsg 函数。 对于给定的套接字,I/O 完成例程不会嵌套。 这允许时间敏感型数据传输完全在先发制人的上下文中进行。
lpOverlapped 参数必须在重叠操作期间有效。 如果多个 I/O 操作同时未完成,则每个操作都必须引用单独的 WSAOVERLAPPED 结构。
如果 lpCompletionRoutine 参数为 NULL,则当重叠操作完成时,如果它包含有效的事件对象句柄,则会向 lpOverlapped 的 hEvent 参数发出信号。 应用程序可以使用 WSAWaitForMultipleEvents 或 WSAGetOverlappedResult 等待或轮询事件对象。
如果 lpCompletionRoutine 不为 NULL,则 忽略 hEvent 参数,应用程序可以使用该参数将上下文信息传递给完成例程。 为同一重叠 I/O 请求传递非 NULLlpCompletionRoutine 并随后调用 WSAGetOverlappedResult 的调用方可能不会将 WSAGetOverlappedResult 的 fWait 参数设置为 TRUE。 在这种情况下, hEvent 参数的用法未定义,并且尝试等待 hEvent 参数会产生不可预知的结果。
完成例程遵循 Windows 文件 I/O 完成例程规定的相同规则。 在调用 fAlertable 参数设置为 TRUE 的函数 WSAWaitForMultipleEvents 时,不会调用完成例程,直到线程处于可警报的等待状态,例如 。
完成例程的原型如下所示:
void CALLBACK CompletionRoutine(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
CompletionRoutine 是应用程序定义或库定义的函数名称的占位符。 dwError 参数指定重叠操作的完成状态,如 lpOverlapped 参数所示。 cbTransferred 参数指定接收的字节数。 如果接收操作立即完成,则 dwFlags 参数包含也会在 lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员中返回的信息。 CompletionRoutine 函数不返回值。
从此函数返回允许为此套接字调用另一个挂起的完成例程。 使用 WSAWaitForMultipleEvents 时,调用所有等待完成例程,然后才能满足可警报线程的等待,返回代码 为 WSA_IO_COMPLETION。 可以按任何顺序调用完成例程,不一定按照重叠操作完成的顺序调用。 但是,保证按指定的相同顺序填充已发布的缓冲区。
如果使用 I/O 完成端口,请注意,对 WSARecvMsg 的调用顺序也是缓冲区的填充顺序。 不应从不同的线程同时在同一套接字上调用 WSARecvMsg 函数,因为它可能会导致不可预知的缓冲区顺序。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 10内部版本 20348 |
最低受支持的服务器 | Windows 10内部版本 20348 |
标头 | mswsock.h |