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 IOCTLs

[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
lpvInBufferlpvOutBufferllpOverlappedlpCompletionRoutine 参数未完全包含在用户地址空间的有效部分中, 或 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 函数用于设置或检索与套接字、传输协议或通信子系统关联的操作参数。

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

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

任何 IOCTL 可能会无限期阻止,具体取决于服务提供商的实现。 如果应用程序不能容忍在 WSAIoctl 调用中阻止,则特别可能阻止的 I/O 会建议重叠 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 操作码,同时提供一种便捷的方式,将操作码标识符空间分区到与 dwIoControlCode 参数一样多,现在是一个 32 位实体。 dwIoControlCode 参数是为了在添加新的控制代码时允许协议和供应商独立,同时保留与 Windows 套接字 1.1 和 Unix 控制代码的向后兼容性。 dwIoControlCode 参数采用以下格式。

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。
 
如果输入缓冲区对代码有效,则设置为 IOC_IN

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

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

T 是一个 2 位数量,用于定义 IOCTL 的类型。 定义了以下值:

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

CompletionRoutine 的 dwError 参数指定重叠操作的完成状态,如 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 应用]
目标平台 窗户
标头 winsock2.h
Ws2_32.lib
DLL Ws2_32.dll

另请参阅

SOL_SOCKET 套接字选项

WSASocket

Winsock 函数

Winsock 参考

getsockopt

ioctlsocket

setsockopt

套接字