WSAIoctl 函数 (winsock2.h)

WSAIoctl 函数控制套接字的模式。

语法

int WSAAPI WSAIoctl(
  [in]  SOCKET                             s,
  [in]  DWORD                              dwIoControlCode,
  [in]  LPVOID                             lpvInBuffer,
  [in]  DWORD                              cbInBuffer,
  [out] LPVOID                             lpvOutBuffer,
  [in]  DWORD                              cbOutBuffer,
  [out] LPDWORD                            lpcbBytesReturned,
  [in]  LPWSAOVERLAPPED                    lpOverlapped,
  [in]  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

参数

[in] s

标识套接字的描述符。

[in] dwIoControlCode

要执行的操作的控制代码。 请参阅 Winsock IOCTL

[in] lpvInBuffer

指向输入缓冲区的指针。

[in] cbInBuffer

输入缓冲区的大小(以字节为单位)。

[out] lpvOutBuffer

指向输出缓冲区的指针。

[in] cbOutBuffer

输出缓冲区的大小(以字节为单位)。

[out] lpcbBytesReturned

指向输出的实际字节数的指针。

[in] lpOverlapped

对于非重叠套接字) , (忽略指向 WSAOVERLAPPED 结构的指针。

[in] lpCompletionRoutine

类型:_In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

注意 指向完成操作时调用的完成例程的指针, (忽略非重叠套接字) 。 请参阅“备注”。
 

返回值

成功完成后, WSAIoctl 返回零。 否则,将返回值 SOCKET_ERROR,并且可以通过调用 WSAGetLastError 来检索特定的错误代码。

错误代码 含义
WSA_IO_PENDING
已成功启动重叠操作,稍后将指示完成。
WSAENETDOWN
网络子系统失败。
WSAEFAULT
lpvInBufferlpvOutBufferlcbBytesReturnedlpOverlappedlpCompletionRoutine 参数未完全包含在用户地址空间的有效部分,或者 cbInBuffercbOutBuffer 参数太小。
WSAEINVAL
dwIoControlCode 参数不是有效的命令,或者指定的输入参数不可接受,或者该命令不适用于指定的套接字类型。
WSAEINPROGRESS
当回调正在进行时,将调用 函数。
WSAENOTSOCK
描述符 不是 套接字。
WSAEOPNOTSUPP
无法实现指定的 IOCTL 命令。 (例如,无法满足 SIO_SET_QOSSIO_SET_GROUP_QOS 中指定的 FLOWSPEC 结构。)
WSAEWOULDBLOCK
套接字标记为非阻塞,请求的操作将阻止。
WSAENOPROTOOPT
指定协议不支持套接字选项。 例如,尝试在 IPv6 套接字上使用 SIO_GET_BROADCAST_ADDRESS IOCTL,或者在数据报套接字上尝试使用 TCP SIO_KEEPALIVE_VALS IOCTL。

注解

WSAIoctl 函数用于设置或检索与套接字、传输协议或通信子系统关联的操作参数。

如果 lpOverlappedlpCompletionRoutine 均为 NULL,则此函数中的套接字将被视为非重叠套接字。 对于非重叠套接字, 将忽略 lpOverlappedlpCompletionRoutine 参数,这会导致函数的行为类似于标准 ioctlsocket 函数,只不过 当套接字 处于 阻塞模式时,函数可以阻止。 如果 套接字 处于 非阻止模式,则当无法立即完成指定的操作时,此函数可以返回 WSAEWOULDBLOCK。 在这种情况下,应用程序可能会将套接字更改为阻止模式,并重新发出请求或等待相应的网络事件 ((如FD_ROUTING_INTERFACE_CHANGE或FD_ADDRESS_LIST_CHANGE)的情况下,SIO_ROUTING_INTERFACE_CHANGE或SIO_ADDRESS_LIST_CHANGE) 使用 WSAAsyncSelect 基于) 或事件 (使用 WSAEventSelect) 通知机制的 Windows 消息 (。

对于重叠的套接字,将启动无法立即完成的操作,并在以后指示完成。 可以忽略返回的lBytesReturned 参数指向的 DWORD 值。 当操作完成时发出相应的完成方法信号时,可以检索返回的最终完成状态和字节数。

任何 IOCTL 都可能无限期阻止,具体取决于服务提供商的实现。 如果应用程序不能容忍 WSAIoctl 调用中的阻塞,则对于特别可能阻止的 IOCTL,建议使用重叠 I/O,其中包括:

SIO_ADDRESS_LIST_CHANGE

SIO_FINDROUTE

SIO_FLUSH

SIO_GET_QOS

SIO_GET_GROUP_QOS

SIO_ROUTING_INTERFACE_CHANGE

SIO_SET_QOS

SIO_SET_GROUP_QOS

某些特定于协议的 IOCTL 也可能特别可能阻止。 有关任何可用信息,请查看特定于协议的相关附件。

lpCompletionRoutine 参数指向的完成例程的原型如下所示:

#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")


void CALLBACK CompletionRoutine (
  IN DWORD dwError,
  IN DWORD cbTransferred,
  IN LPWSAOVERLAPPED lpOverlapped,
  IN DWORD dwFlags 
);

CompletionRoutine 是应用程序提供的函数名称的占位符。 dwError 参数指定重叠操作的完成状态,如 lpOverlapped 参数所示。 cbTransferred 参数指定接收的字节数。 dwFlags 参数不用于此 IOCTL。 完成例程不返回值。

可以采用一种编码方案来保留当前定义的 ioctlsocket 操作码,同时提供一种方便的方法,将操作码标识符空间分区到 32 位实体中,就像 dwIoControlCode 参数现在是一个 32 位实体一样。 dwIoControlCode 参数的构建是为了在添加新控制代码时允许协议和供应商独立性,同时保持与 Windows 套接字 1.1 和 Unix 控制代码的向后兼容性。 dwIoControlCode 参数具有以下形式。

I O V T 供应商/地址系列 代码
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 
注意 表中显示的 dwIoControlCode 参数中的位必须按列从上到下垂直读取。 因此,最左边的位是位 31,下一位是位 30,最右边的位是位 0。
 
如果输入缓冲区对代码有效,则设置 I,就像 IOC_IN一样。

如果输出缓冲区对代码有效,则设置 O,就像 IOC_OUT一样。 使用输入和输出缓冲区设置 I 和 O 的控制代码。

如果代码没有参数,则设置 V,就像 IOC_VOID一样。

T 是定义 IOCTL 类型的 2 位数量。 定义了以下值:

0 IOCTL 是标准的 Unix IOCTL 代码,与 FIONREADFIONBIO 一样。

1 IOCTL 是通用 Windows 套接字 2 IOCTL 代码。 为 Windows 套接字 2 定义的新 IOCTL 代码的 T == 1。

2 IOCTL 仅适用于特定地址系列。

3 IOCTL 仅适用于特定供应商的提供商,与 IOC_VENDOR 一样。 此类型允许向公司分配显示在 Vendor/Address 系列 参数中的供应商编号。 然后,供应商可以定义特定于该供应商的新 IOCTL,而无需向清算所注册 IOCTL,从而提供供应商的灵活性和隐私性。

供应商/地址系列 一个 11 位数量,定义拥有代码 ((如果 T == 3) )或包含代码 ((如果 T == 2) )的地址系列的供应商。 如果这是 (T == 0) 的 Unix IOCTL 代码,则此参数与 Unix 上的代码具有相同的值。 如果这是通用 Windows 套接字 2 IOCTL (T == 1) 则此参数可用作代码参数的扩展来提供其他代码值。

代码 包含操作的特定 IOCTL 代码的 16 位数量。

支持以下 Unix IOCTL 代码 (命令) 。

支持以下 Windows 套接字 2 命令。

如果重叠操作立即完成, WSAIoctl 将返回一个零值,并使用输出缓冲区中的字节数更新 lhttpBytesReturned 参数。 如果已成功启动重叠操作并将稍后完成,此函数将返回SOCKET_ERROR并指示 错误代码WSA_IO_PENDING。 在本例中, 不会更新lBytesReturned 。 当重叠操作完成时,输出缓冲区中的数据量将通过完成例程 (中的 cbTransferred 参数(如果指定) )或通过 WSAGetOverlappedResult 中的 lcbTransfer 参数指示。

使用重叠套接字调用时, lpOverlapped 参数必须在重叠操作期间有效。 lpOverlapped 参数包含 WSAOVERLAPPED 结构的地址。

如果 lpCompletionRoutine 参数为 NULL,则当重叠操作完成时,如果它包含有效的事件对象句柄,则会向 lpOverlappedhEvent 参数发出信号。 应用程序可以使用 WSAWaitForMultipleEventsWSAGetOverlappedResult 等待或轮询事件对象。

注意 当给定线程退出时,将取消由该线程发起的所有 I/O。 对于重叠的套接字,如果在操作完成之前关闭线程,挂起的异步操作可能会失败。 有关详细信息 ,请参阅 ExitThread
 
如果 lpCompletionRoutine 不为 NULL,则 忽略 hEvent 参数,应用程序可以使用该参数将上下文信息传递给完成例程。 为同一重叠 I/O 请求传递非 NULLlpCompletionRoutine 并随后调用 WSAGetOverlappedResult 的调用方可能不会将 WSAGetOverlappedResultfWait 参数设置为 TRUE。 在这种情况下, hEvent 参数的使用未定义,并且尝试等待 hEvent 参数会产生不可预知的结果。

完成例程的原型如下所示:


void CALLBACK CompletionRoutine(
  IN DWORD dwError, 
  IN DWORD cbTransferred, 
  IN LPWSAOVERLAPPED lpOverlapped, 
  IN DWORD dwFlags 
);

CompletionRoutine 是应用程序定义的函数或库定义的函数的占位符。 仅当线程处于可警报状态时,才会调用完成例程。 若要将线程置于可警报状态,请使用 WSAWaitForMultipleEventsWaitForSingleObjectExWaitForMultipleObjectsEx 函数,并将 fAlertablebAlertable 参数设置为 TRUE

CompletionRoutinedwError 参数指定重叠操作的完成状态,如 lpOverlapped 所示。 cbTransferred 参数指定返回的字节数。 目前,未定义标志值, dwFlags 将为零。 CompletionRoutine 函数不返回值。

从此函数返回允许为此套接字调用另一个挂起的完成例程。 可以按任何顺序调用完成例程,不一定按照重叠操作完成的顺序调用。

兼容性

T == 0 的 IOCTL 代码是伯克利套接字中使用的 IOCTL 代码的子集。 具体而言,没有等效于 FIOASYNC 的命令。
注意 某些 IOCTL 代码需要其他头文件。 例如,使用 SIO_RCVALL IOCTL 需要 Mstcpip.h 头文件。
 
Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。

要求

要求
最低受支持的客户端 Windows 8.1、Windows Vista [桌面应用 |UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 winsock2.h
Library Ws2_32.lib
DLL Ws2_32.dll

另请参阅

SOL_SOCKET套接字选项

WSASocket

Winsock 函数

Winsock 参考

getsockopt

ioctlsocket

setsockopt

socket