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 以外的值。 下表列出了错误代码。
WSASendMsg 函数可用于代替 WSASend 和 WSASendTo 函数。 WSASendMsg 函数只能与数据报和原始套接字一起使用。 必须打开 s 参数中的套接字描述符,并将套接字类型设置为 SOCK_DGRAM 或 SOCK_RAW。
dwFlags 参数只能包含以下控件标志的组合:MSG_DONTROUTE、MSG_PARTIAL和MSG_OOB。 lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员在输入时将被忽略,而不用于输出。
注意必须在运行时通过调用 WSAIoctl 函数并指定
SIO_GET_EXTENSION_FUNCTION_POINTER操作码来获取
WSASendMsg 函数的函数指针。
传递给 WSAIoctl 函数的输入缓冲区必须包含 WSAID_WSASENDMSG,这是一个全局唯一标识符, (GUID) 其值标识 WSASendMsg 扩展函数。 成功后, WSAIoctl 函数返回的输出包含指向 WSASendMsg 函数的指针。 WSAID_WSASENDMSG GUID 在 Mswsock.h 头文件中定义。
重叠套接字是使用设置了 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 源地址。
注意SO_SNDTIMEO套接字选项仅适用于阻止套接字。
注意成功完成 WSASendMsg 并不表示数据已成功传递。
注意 在发出阻止 Winsock 调用(例如 WSASendMsg 且 lpOverlapped 参数设置为 NULL)时,Winsock 可能需要等待网络事件,然后调用才能完成。 在这种情况下,Winsock 执行可发出警报的等待, (在同一线程上计划的 APC) 异步过程调用可能会中断该等待。 在 APC 内发出另一个阻止 Winsock 调用,该调用中断了同一线程上正在进行的阻止 Winsock 调用将导致未定义的行为,并且 Winsock 客户端绝不能尝试。
dwFlags 输入参数可用于在为关联套接字指定的选项之外影响函数调用的行为。 也就是说,此函数的语义由套接字选项和 dwFlags 参数确定。 后者是使用以下任一值的按位 OR 运算符构造的。
dwFlags 参数的可能值在 Winsock2.h 头文件中定义。
输出时,不使用 lpMsg 参数指向的 WSAMSG 结构的 dwFlags 成员。
如果重叠操作立即完成, WSASendMsg 将返回零值,并使用发送的字节数更新 lpNumberOfBytesSent 参数。 如果重叠操作已成功启动并将稍后完成, 则 WSASendMsg 将返回SOCKET_ERROR并指示 错误代码WSA_IO_PENDING。 在这种情况下,不会更新 lpNumberOfBytesSent 。 重叠操作完成后,将通过完成例程中的 cbTransferred 参数 ((如果) 指定)或通过 WSAGetOverlappedResult 中的 lcbTransfer 参数指示传输的数据量。
注意 当给定线程退出时,将取消由该线程发起的所有 I/O。 对于重叠的套接字,如果在操作完成之前关闭线程,挂起的异步操作可能会失败。 有关详细信息
,请参阅 ExitThread 。
可以使用重叠 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 应用商店应用支持此函数。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:https://aka.ms/ContentUserFeedback。提交和查看相关反馈
MSG_DONTROUTE |
:指定数据不应受到路由的约束。 Windows 套接字服务提供程序可以选择忽略此标志。 |
MSG_PARTIAL |
指定 lpMsg-lpBuffers> 仅包含部分消息。 请注意,不支持部分消息传输的传输将返回错误代码 WSAEOPNOTSUPP 。 |