WSASendMsg 函数 (winsock2.h)
WSASendMsg 函数从连接的和未连接的套接字发送数据和可选控制信息。
语法
int WSAAPI WSASendMsg(
[in] SOCKET Handle,
[in] LPWSAMSG lpMsg,
[in] DWORD dwFlags,
[out] LPDWORD lpNumberOfBytesSent,
[in] LPWSAOVERLAPPED lpOverlapped,
[in] LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
参数
[in] Handle
标识套接字的描述符。
[in] lpMsg
存储 Posix.1g msghdr 结构的 WSAMSG 结构。
[in] dwFlags
用于修改 WSASendMsg 函数调用行为的标志。 有关详细信息,请参阅“备注”部分中的 Using dwFlags 。
[out] lpNumberOfBytesSent
如果 I/O 操作立即完成,则指向此调用发送的数字(以字节为单位)的指针。
如果 lpOverlapped 参数不是 NULL,请对此参数使用 NULL,以避免潜在的错误结果。 仅当 lpOverlapped 参数不为 NULL 时,此参数才能为 NULL。
[in] lpOverlapped
指向 WSAOVERLAPPED 结构的指针。 对于非重叠套接字忽略。
[in] lpCompletionRoutine
类型:_In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
指向发送操作完成时调用的完成例程的指针。 对于非重叠套接字忽略。
返回值
成功且立即完成时返回零。 返回零时,当调用线程处于可警报状态时,将调用指定的完成例程。
返回值 SOCKET_ERROR,随后调用 WSAGetLastError (返回WSA_IO_PENDING)指示已成功启动重叠操作;然后,通过其他方式(例如通过事件或完成端口)指示完成。
失败时, 返回 SOCKET_ERROR ,对 WSAGetLastError 的后续调用将返回 除 WSA_IO_PENDING 以外的值。 下表列出了错误代码。
错误代码 | 含义 |
---|---|
:请求的地址是广播地址,但相应的标志未设置。 | |
对于 UDP 数据报套接字,此错误将指示以前的发送操作导致 ICMP“端口无法访问”消息。 | |
lpMsg、lpNumberOfBytesSent、lpOverlapped 或 lpCompletionRoutine 参数并不完全包含在用户地址空间的有效部分。 如果 lpMsg 参数指向的 WSAMSG 结构的名称成员是 NULL 指针,并且 WSAMSG 结构的 namelen 成员未设置为零,则也会返回此错误。 如果 lpMsg 参数指向的 WSAMSG 结构的 Control.buf 成员是 NULL 指针,并且 WSAMSG 结构的 Control.len 成员未设置为零,则也会返回此错误。 | |
阻止 Windows Sockets 1.1 调用正在进行,或者服务提供程序仍在处理回调函数。 | |
阻止的 Windows 套接字 1.1 调用已通过 WSACancelBlockingCall 取消。 | |
套接字未绑定 绑定,或者未使用重叠标志创建套接字。 | |
套接字面向消息,消息大于基础传输支持的最大大小。 | |
网络子系统失败。 | |
对于数据报套接字,此错误显示生存时间已经过期。 | |
无法访问网络。 | |
Windows 套接字提供程序报告缓冲区死锁。 | |
套接字未连接。 | |
:描述符不是套接字。 | |
不支持套接字操作。 如果 lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员包含 WSASendMsg 无效的任何控制标志,则返回此错误。 | |
套接字已关闭;在调用关闭后,无法在套接字上调用 WSASendMsg 函数,以及如何将 设置为 SD_SEND 或 SD_BOTH。 | |
套接字超时。如果套接字使用 SO_SNDTIMEO 套接字选项指定了等待超时,并且超过超时,则返回此错误。 | |
重叠套接字:存在过多未完成的重叠 I/O 请求。 未重叠的套接字:套接字标记为非阻止,并且无法立即完成发送操作。 | |
在使用此函数之前,必须成功调用 WSAStartup 。 | |
已成功启动重叠操作,稍后将指示完成。 | |
由于套接字关闭或 WSAIoctl 中执行 SIO_FLUSH 命令,重叠操作已取消。 |
注解
WSASendMsg 函数可用于代替 WSASend 和 WSASendTo 函数。 WSASendMsg 函数只能与数据报和原始套接字一起使用。 必须打开 s 参数中的套接字描述符,并将套接字类型设置为 SOCK_DGRAM 或 SOCK_RAW。
dwFlags 参数只能包含以下控件标志的组合:MSG_DONTROUTE、MSG_PARTIAL和MSG_OOB。 lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员在输入时将被忽略,而不用于输出。
重叠套接字是使用设置了 WSA_FLAG_OVERLAPPED 标志的 WSASocket 函数调用创建的。 对于重叠套接字,除非 lpOverlapped 和 lpCompletionRoutine 均为 NULL,否则发送信息使用重叠 I/O;当 lpOverlapped 和 lpCompletionRoutine 为 NULL 时,套接字被视为未重叠的套接字。 重叠的套接字出现完成指示;传输使用缓冲区或缓冲区后,将触发完成例程或设置事件对象。 如果操作未立即完成,则通过完成例程或通过调用 WSAGetOverlappedResult 函数检索最终完成状态。
对于非重叠套接字,将忽略 lpOverlapped 和 lpCompletionRoutine 参数, WSASendMsg 采用与 send 函数相同的阻塞语义:数据从缓冲区或缓冲区复制到传输的缓冲区中。 如果套接字是非阻塞且面向流的,并且传输的缓冲区中空间不足, 则 WSASendMsg 将返回,只使用应用程序的部分缓冲区。 相比之下,阻塞套接字上的这种缓冲区情况会导致 WSASendMsg 阻塞,直到应用程序的所有缓冲区内容都已使用。
如果此函数以重叠方式完成,则 Winsock 服务提供商负责在从此调用返回之前捕获此 WSABUF 结构。 这使应用程序能够生成由 lpMsg 参数指向的 WSAMSG 结构的 lpBuffers 成员所指向的基于堆栈的 WSABUF 数组。
对于面向消息的套接字,必须注意不要超过基础提供程序的最大消息大小,这可以通过 获取套接字选项的值SO_MAX_MSG_SIZE获得。 如果数据太长而无法通过基础协议以原子方式传递,则会返回错误 WSAEMSGSIZE ,并且不会传输任何数据。
在 SOCK_DGRAM 或 SOCK_RAW 类型的 IPv4 套接字上,应用程序可以指定用于通过 WSASendMsg 函数发送的本地 IP 源地址。 在 WSAMSG 结构中传递给 WSASendMsg 函数的一个控制数据对象可能包含 in_pktinfo 结构,该结构用于指定要用于发送的本地 IPv4 源地址。
在 SOCK_DGRAM 或 SOCK_RAW 类型的 IPv6 套接字上,应用程序可以指定用于与 WSASendMsg 函数一起发送的本地 IP 源地址。 在 WSAMSG 结构中传递给 WSASendMsg 函数的控制数据对象之一可能包含用于指定要用于发送的本地 IPv6 源地址 的in6_pktinfo 结构。
对于使用 WSASendMsg 函数发送数据报且应用程序想要指定要使用的特定本地 IP 源地址时,双堆栈套接字的处理方法取决于目标 IP 地址。 当发送到 IPv4 目标地址或 IPv4 映射的 IPv6 目标地址时,在 lpMsg 参数指向的 WSAMSG 结构中传递的控制数据对象之一应包含包含用于发送的本地 IPv4 源地址的in_pktinfo结构。 当发送到不是 IPv4 映射的 IPv6 地址的 IPv6 目标地址时,在 lpMsg 参数指向的 WSAMSG 结构中传递的控制数据对象之一应包含in6_pktinfo结构,其中包含用于发送的本地 IPv6 源地址。
dwFlags
dwFlags 输入参数可用于在为关联套接字指定的选项之外影响函数调用的行为。 也就是说,此函数的语义由套接字选项和 dwFlags 参数确定。 后者是使用以下任一值的按位 OR 运算符构造的。值 | 含义 |
---|---|
MSG_DONTROUTE | :指定数据不应受到路由的约束。 Windows 套接字服务提供程序可以选择忽略此标志。 |
MSG_PARTIAL | 指定 lpMsg-lpBuffers> 仅包含部分消息。 请注意,不支持部分消息传输的传输将返回错误代码 WSAEOPNOTSUPP 。 |
输出时,不使用 lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员。
重叠套接字 I/O
如果重叠操作立即完成, WSASendMsg 将返回零值,并使用发送的字节数更新 lpNumberOfBytesSent 参数。 如果重叠操作已成功启动并将稍后完成, 则 WSASendMsg 将返回SOCKET_ERROR并指示 错误代码WSA_IO_PENDING。 在这种情况下,不会更新 lpNumberOfBytesSent 。 重叠操作完成后,将通过完成例程中的 cbTransferred 参数 ((如果) 指定)或通过 WSAGetOverlappedResult 中的 lcbTransfer 参数指示传输的数据量。可以使用重叠 I/O 的 WSASendMsg 函数从以前的 、WSARecv、WSARecvFromLPFN_WSARECVMSG (WSARecvMsg) 、WSASend、WSASendMsg 或 WSASendTo 函数的完成例程中调用。 这允许时间敏感型数据传输完全在先发制人的上下文中进行。
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。
传输提供程序允许应用程序从套接字 I/O 完成例程的上下文中调用发送和接收操作,并保证对于给定套接字,I/O 完成例程不会嵌套。 这允许时间敏感型数据传输完全在先发制人的上下文中进行。
完成例程的原型如下所示。
void CALLBACK CompletionRoutine(
IN DWORD dwError,
IN DWORD cbTransferred,
IN LPWSAOVERLAPPED lpOverlapped,
IN DWORD dwFlags
);
CompletionRoutine 函数是应用程序定义或库定义的函数名称的占位符。 dwError 参数指定重叠操作的完成状态,如 lpOverlapped 参数所示。 cbTransferred 参数指示发送的字节数。 当前未定义标志值, dwFlags 参数将为零。 CompletionRoutine 函数不返回值。
从此函数返回允许调用套接字的另一个挂起完成例程。 所有等待完成例程在可警报线程的等待得到满足之前调用,返回代码为 WSA_IO_COMPLETION。 可以按任何顺序调用完成例程,不一定按照重叠操作完成的顺序调用。 但是,可以保证按指定的相同顺序发送已发布的缓冲区。
Windows 8.1和Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 8.1、Windows Vista [桌面应用 |UWP 应用] |
最低受支持的服务器 | Windows Server 2008 [桌面应用 | UWP 应用] |
目标平台 | Windows |
标头 | winsock2.h (包括 Mswsock.h) |
Library | Ws2_32.lib |
DLL | Ws2_32.dll |
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈