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 函数调用行为的标志。 有关详细信息,请参阅“备注”部分中的“使用 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 参数未完全包含在用户地址空间的有效部分中。 如果 |
|
正在阻止 Windows 套接字 1.1 调用,或者服务提供商仍在处理回调函数。 | |
WSACancelBlockingCall取消了阻止的 Windows 套接字 1.1 调用。 | |
套接字未绑定到 绑定,或者未使用重叠标志创建套接字。 | |
套接字面向消息,并且消息大于基础传输支持的最大大小。 | |
网络子系统已失败。 | |
对于数据报套接字,此错误指示生存时间已过期。 | |
网络无法访问。 | |
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 和 lpCompletionRoutineNULL,否则发送信息将使用重叠的 I/O;当 lpOverlapped 和 lpCompletionRoutineNULL时,套接字将被视为非重叠套接字。 完成指示与重叠套接字一起发生;传输使用缓冲区或缓冲区后,将触发完成例程或设置事件对象。 如果操作未立即完成,则通过完成例程或通过调用 WSAGetOverlappedResult 函数来检索最终完成状态。
对于非重叠套接字,lpOverlapped 和 lpCompletionRoutine 参数将被忽略,WSASendMsg 采用与 发送 函数相同的阻塞语义:数据从缓冲区或缓冲区复制到传输的缓冲区中。 如果套接字不阻塞且面向流,并且传输缓冲区中空间不足,则 WSASendMsg 返回,并且只使用应用程序的缓冲区的一部分。 相比之下,阻止套接字上的此缓冲区情况会导致 WSASendMsg 阻塞,直到所有应用程序的缓冲区内容都已使用。
如果此函数以重叠的方式完成,则 Winsock 服务提供商有责任在从此调用返回之前捕获此 WSABUF 结构。 这使应用程序能够生成基于堆栈的 WSABUF 数组,这些数组由 WSAMSG 结构 lpMsg 参数指向的 lpBuffers 成员。
对于面向消息的套接字,必须小心不要超过基础提供程序的最大消息大小,这可以通过获取套接字选项的值 SO_MAX_MSG_SIZE获得。 如果数据太长,无法通过基础协议以原子方式传递,则会返回 WSAEMSGSIZE 错误,并且不会传输任何数据。
在类型 SOCK_DGRAM 或 SOCK_RAW的 IPv4 套接字上,应用程序可以指定用于与 WSASendMsg 函数一起发送的本地 IP 源地址。 WSAMSG 结构中传递给 WSASendMsg 函数的控件数据对象之一可能包含用于指定要用于发送的本地 IPv4 源地址的 in_pktinfo 结构。
在类型 SOCK_DGRAM 或 SOCK_RAW的 IPv6 套接字上,应用程序可以指定用于与 WSASendMsg 函数一起发送的本地 IP 源地址。 WSAMSG 结构中传递给 WSASendMsg 函数的控件数据对象之一可能包含用于指定要用于发送的本地 IPv6 源地址的 in6_pktinfo 结构。
对于使用 WSASendMsg 函数发送数据报时双堆栈套接字,应用程序想要指定要使用的特定本地 IP 源地址,处理此方法取决于目标 IP 地址。 发送到 IPv4 目标地址或 IPv4 映射的 IPv6 目标地址时,WSAMSG 结构中传递的其中一个控制数据对象应包含由 lpMsg 参数指向的 in_pktinfo 结构,该结构包含用于发送的本地 IPv4 源地址。 发送到不是 IPv4 映射 IPv6 地址的 IPv6 目标地址时,WSAMSG 结构中传递的控制数据对象之一应包含 lpMsg 参数指向的 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 参数来指示传输的数据量。lpOverlapped 参数在重叠操作期间必须有效。 如果多个 I/O 操作同时未完成,则每个操作都必须引用单独的 WSAOVERLAPPED 结构。
如果 lpCompletionRoutine 参数 NULL,则当重叠操作包含有效事件对象句柄时,lpOverlapped 的 hEvent 参数发出信号。 应用程序可以使用 WSAWaitForMultipleEvents 或 WSAGetOverlappedResult 等待或轮询事件对象。
如果 lpCompletionRoutine 未 NULL,则应用程序将忽略 hEvent 参数,并可供应用程序用来将上下文信息传递给完成例程。 传递非NULLlpCompletionRoutine 的调用方,并且对于同一重叠 I/O 请求,WSAGetOverlappedResult,则不能为调用 WSAGetOverlappedResult 设置 fWait 参数,以 TRUE。 在这种情况下,未定义 hEvent 参数的使用,并且尝试等待 hEvent 参数将产生不可预知的结果。
完成例程遵循与 Windows 文件 I/O 完成例程规定的相同规则。 在线程处于可警报等待状态之前,不会调用完成例程,例如,调用 WSAWaitForMultipleEvents,fAlertable 参数设置为 TRUE。
传输提供程序允许应用程序从套接字 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 应用] |
目标平台 | 窗户 |
标头 | winsock2.h (包括 Mswsock.h) |
库 | Ws2_32.lib |
DLL | Ws2_32.dll |