SIO_SET_COMPATIBILITY_MODE控制代码
说明
SIO_SET_COMPATIBILITY_MODE控制代码请求网络堆栈应如何处理某些行为,这些行为的默认处理方式可能因 Windows 版本而异。
若要执行此操作,请使用以下参数调用 WSAIoctl 或 WSPIoctl 函数。
int WSAIoctl(
(socket) s, // descriptor identifying a socket
SIO_SET_COMPATIBILITY_MODE, // dwIoControlCode
(LPVOID) lpvInBuffer, // pointer to WSA_COMPATIBILITY_MODE struct
(DWORD) cbInBuffer, // length of input buffer
NULL, // output buffer
0, // size of output buffer
(LPDWORD) lpcbBytesReturned, // number of bytes returned
(LPWSAOVERLAPPED) lpOverlapped, // OVERLAPPED structure
(LPWSAOVERLAPPED_COMPLETION_ROUTINE) lpCompletionRoutine, // completion routine
);
int WSPIoctl(
(socket) s, // descriptor identifying a socket
SIO_SET_COMPATIBILITY_MODE, // dwIoControlCode
(LPVOID) lpvInBuffer, // pointer to WSA_COMPATIBILITY_MODE struct
(DWORD) cbInBuffer, // length of input buffer
NULL, // output buffer
0, // size of output buffer
(LPDWORD) lpcbBytesReturned, // number of bytes returned
(LPWSAOVERLAPPED) lpOverlapped, // OVERLAPPED structure
(LPWSAOVERLAPPED_COMPLETION_ROUTINE) lpCompletionRoutine, // completion routine
(LPWSATHREADID) lpThreadId, // a WSATHREADID structure
(LPINT) lpErrno // a pointer to the error code.
);
参数
S
标识套接字的描述符。
dwIoControlCode
操作的控制代码。 对此操作使用 SIO_SET_COMPATIBILITY_MODE 。
lpvInBuffer
指向输入缓冲区的指针。 此参数应指向 WSA_COMPATIBILITY_MODE 结构。
cbInBuffer
输入缓冲区的大小(以字节为单位)。 此参数应等于或大于 lpvInBuffer 参数指向的WSA_COMPATIBILITY_MODE结构的大小。
lpvOutBuffer
指向输出缓冲区的指针。 此参数未用于此操作。
cbOutBuffer
输出缓冲区的大小(以字节为单位)。 该参数必须设置为零。
lhttpBytesReturned
指向变量的指针,该变量接收输出缓冲区中存储的数据的大小(以字节为单位)。 此返回的参数指向此操作的 DWORD 值零,因为没有输出。
lpvOverlapped
指向 WSAOVERLAPPED 结构的指针。
如果 创建的套接字 没有重叠属性,则忽略 lpOverlapped 参数。
如果使用重叠属性打开了 , 并且 lpOverlapped 参数不为 NULL,则该操作将作为重叠 (异步) 操作执行。 在这种情况下, lpOverlapped 参数必须指向有效的 WSAOVERLAPPED 结构。
对于重叠操作, WSAIoctl 或 WSPIoctl 函数将立即返回,并在操作完成时发出相应的完成方法信号。 否则,在操作完成或发生错误之前,函数不会返回 。
lpCompletionRoutine
类型:_In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
指向完成操作时调用的完成例程的指针, (忽略非重叠套接字) 。
lpThreadId
指向 WSATHREADID 结构的指针,供提供程序在后续调用 WPUQueueApc 时使用。 在 WPUQueueApc 函数返回之前,提供程序应存储引用的 WSATHREADID 结构 (而不是指向同一) 的指针。
注意 此参数仅适用于 WSPIoctl 函数。
lpErrno
指向错误代码的指针。
注意 此参数仅适用于 WSPIoctl 函数。
返回值
如果操作成功完成, WSAIoctl 或 WSPIoctl 函数将返回零。
如果操作失败或挂起, WSAIoctl 或 WSPIoctl 函数将返回 SOCKET_ERROR。 若要获取扩展的错误信息,请调用 WSAGetLastError。
错误代码 | 含义 |
---|---|
WSA_IO_PENDING | 已成功启动重叠操作,稍后将指示完成。 |
WSA_OPERATION_ABORTED | 由于套接字关闭或执行 了 SIO_FLUSH IOCTL 命令,已取消重叠的操作。 |
WSAEFAULT | lpOverlapped 或 lpCompletionRoutine 参数并不完全包含在用户地址空间的有效部分。 |
WSAEINPROGRESS | 当回调正在进行时,将调用 函数。 |
WSAEINTR | 阻止操作中断。 |
WSAEINVAL | dwIoControlCode 参数不是有效的命令,或者指定的输入参数不可接受,或者该命令不适用于指定的套接字类型。 如果 cbInBuffer 参数小于 WSA_COMPATIBILITY_MODE 结构的大小,则返回此错误。 |
WSAENETDOWN | 网络子系统失败。 |
WSAENOPROTOOPT | 指定协议不支持套接字选项。 |
WSAENOTCONN | 套接字未连接。 |
WSAENOTSOCK | 描述符 不是 套接字。 |
WSAEOPNOTSUPP | 不支持指定的 IOCTL 命令。 如果传输提供程序不支持 SIO_SET_COMPATIBILITY_MODE IOCTL,则返回此错误。 尝试在数据报套接字上使用 SIO_SET_COMPATIBILITY_MODE IOCTL 时,也会返回此错误。 |
备注
SIO_SET_COMPATIBILITY_MODE IOCTL 请求网络堆栈应如何处理某些行为,这些行为的默认处理方式可能因 Windows 版本而异。 SIO_SET_COMPATIBILITY_MODE的输入参数结构在 Mswsockdef.h 头文件中定义的WSA_COMPATIBILITY_MODE结构中指定。 指向 WSA_COMPATIBILITY_MODE 结构的指针在 cbInBuffer 参数中传递。 此结构定义如下:
// Need to #include <mswsock.h>
/* Argument structure for SIO_SET_COMPATIBILITY_MODE */
typedef struct _WSA_COMPATIBILITY_MODE {
WSA_COMPATIBILITY_BEHAVIOR_ID BehaviorId;
ULONG TargetOsVersion;
} WSA_COMPATIBILITY_MODE, *PWSA_COMPATIBILITY_MODE;
BehaviorId 成员中指定的值指示请求的行为。 TargetOsVersion 成员中指定的值指示正在为该行为请求的 Windows 版本。
BehaviorId 成员可以是 mswsockdef.h 头文件中定义的 WSA_COMPATIBILITY_BEHAVIOR_ID 枚举类型的值之一。 BehaviorId 成员的可能值如下所示:
术语 | 说明 |
---|---|
WsaBehaviorAll | 这相当于请求为 WSA_COMPATIBILITY_BEHAVIOR_ID 定义的所有可能的兼容行为。 |
WsaBehaviorReceiveBuffering | 当 TargetOsVersion 成员设置为 Windows Vista 或更高版本的值时,即使已建立 TCP 连接,也允许使用 SO_RCVBUF 套接字选项减小此套接字上的 TCP 接收缓冲区大小。 如果将 TargetOsVersion 成员设置为早于 Windows Vista 的值,则不允许在建立连接后使用 SO_RCVBUF 套接字选项减小此套接字上的 TCP 接收缓冲区大小。 |
WsaBehaviorAutoTuning | 当 TargetOsVersion 成员设置为 Windows Vista 或更高版本的值时,将启用接收窗口自动优化,并且 TCP 窗口比例系数从默认值 8 减少到 2。 当 TargetOsVersion 设置为早于 Windows Vista 的值时,将禁用接收窗口自动优化。 TCP 窗口缩放选项也被禁用,最大 true 接收窗口大小限制为 65,535 字节。 无法在连接上协商 TCP 窗口缩放选项,即使在建立连接之前在此套接字上调用了 SO_RCVBUF 套接字选项,指定的值大于 65,535 字节。 |
TargetOsVersion 成员可以是 Sdkddkver.h 头文件中定义的 NTDDI 版本常量之一。 TargetOsVersion 成员的一些可能值如下所示:
术语 | 说明 |
---|---|
NTDDI_LONGHORN | 目标行为是 Windows Vista 的默认值。 |
NTDDI_WS03 | 目标行为是 Windows Server 2003 的默认值。 |
NTDDI_WINXP | 目标行为是 Windows XP 的默认行为。 |
NTDDI_WIN2K | 目标行为是 Windows 2000 的默认行为。 |
TargetOsVersion 成员的主要影响是将此成员设置为等于或大于 NTDDI_LONGHORN 的值。
TCP 性能不仅取决于传输速率本身,还取决于传输速率和往返延迟时间的乘积。 此带宽延迟产品测量将“填充管道”的数据量。 此带宽延迟乘积是发送方和接收方通过路径获取 TCP 连接的最大吞吐量所需的缓冲区空间。 此缓冲区空间表示 TCP 必须处理才能使管道充满的未确认数据量。 当带宽延迟积较大时,会出现 TCP 性能问题。 在这些条件下运行的网络路径通常称为“长胖管道”。 示例包括高容量数据包卫星链路、高速无线链路和长途地面光纤链路。
TCP 标头使用 16 位数据字段 (TCP 数据包标头) 的 Window 字段向发送方报告接收窗口大小。 因此,可以使用的最大窗口为 65,535 字节。 为规避此限制,为高性能 TCP 添加了 TCP 扩展选项“TCP 窗口缩放”,以允许大于 65,535 字节的窗口。 WSopt) (TCP 窗口缩放选项在 IETF 网站上提供的 RFC 1323 中定义。 WSopt 扩展使用单字节对数比例因子扩展 TCP 窗口的定义,以扩展 TCP 标头中的 16 位 Window 字段。 WSopt 扩展定义了隐式比例系数 (2 到一些功率) ,用于将 TCP 标头中找到的窗口大小值相乘,以获取真正的窗口大小。 因此,窗口比例系数为 8 将导致真正的窗口大小等于 TCP 标头中 Window 字段中的值乘以 2^8 或 256。 因此,如果将 TCP 标头中的 Window 字段设置为最大值 65,535 字节,并且 WSopt 比例系数协商为值 8,则真正的窗口大小将为 16,776,960 字节。
真正的接收窗口大小,因此比例系数由最大接收缓冲区空间决定。 此最大缓冲区空间是 TCP 接收方允许 TCP 发送方在等待确认之前发送的数据量。 建立连接后,接收窗口大小在每个 TCP 段中播发, (TCP 标头) 的 Window 字段。 播发发送方可以发送的最大数据量是一种接收方流控制机制,该机制可防止发送方发送接收方无法存储的数据。 发送主机只能在等待确认和接收窗口大小更新之前发送接收方播发的最大数据量。
在 Windows Server 2003 和 Windows XP 上,表示 TCP/IP 堆栈的接收窗口大小的最大接收缓冲区空间具有基于发送接口的链接速度的默认值。 实际值会自动调整为在建立 TCP 连接期间协商 (MSS) 最大段大小的偶数增量。 因此,对于 10 Mbit/sec 链接,默认接收窗口大小通常设置为 16K 字节,而在 100 MBit/sec 链接上,默认接收窗口大小将设置为 65,535 字节。
在 Windows Server 2003 和 Windows XP 上,可以使用特定接口或整个系统上的以下注册表值手动配置 TCP/IP 堆栈的真正最大接收窗口大小:
HKEY_LOCAL_MACHINE\SYSTEM\Current Control Set\Services\Tcpip\Parameters\TCPWindowSize
HKEY_LOCAL_MACHINE\SYSTEM\Current Control Set\Services\Tcpip\Parameters\Interface\TCPWindowSize
不使用 WSopt 扩展时,TCPWindowSize 的注册表值可以设置为最大 65,535 字节;如果使用 WSopt 扩展,则最多设置为 1,073,741,823 字节 () 支持最大比例系数 4。 如果没有窗口缩放,应用程序只能实现大约 5 兆位/秒的吞吐量, (Mbps) 路径的往返时间为 100 毫秒, (RTT) ,而不考虑路径带宽。 通过窗口缩放,此吞吐量可以扩展到每秒千兆位 (Gbps) ,这允许 TCP 在建立连接期间协商窗口大小的缩放因子。
在 Windows Server 2003 和 Windows XP 上,可以通过设置以下注册表值来启用 WSopt 扩展。
HKEY_LOCAL_MACHINE\SYSTEM\Current Control Set\Services\Tcpip\Parameters\Tcp1323Opts
Tcp1323Opts 注册表值是经过编码的 DWORD,这样,当设置位 0 时,将启用 TCP WSopt 扩展。 设置位 1 后,将启用 RFC 1323 中定义的 TSopt) (TCP 时间戳选项。 因此,值为 1 或 3 将启用 WSopt 扩展。
在 Windows Server 2003 和 Windows XP 上,默认为不创建 TCPWindowSize 和 Tcp1323Opts 注册表值。 因此,默认情况下,WSopt 扩展处于禁用状态,TCP 接收窗口大小由系统设置为最大为 65,535 字节的最大值,具体取决于链接速度。 如果通过设置 Tcp1323Opts 注册表值在 Windows Server 2003 和 Windows XP 上启用窗口缩放,则仅当发送方和接收方在同步 (SYN) 段中包含 TCP 窗口缩放选项以协商窗口缩放因子时,才仍对 TCP 连接使用窗口缩放。 在连接上使用窗口缩放时,TCP 标头中的“窗口”字段设置为 65,535 字节,窗口缩放因子用于通过建立连接时协商的窗口比例因子向上调整真正的接收窗口大小。
应用程序可以使用 SO_RCVBUF 套接字选项指定连接的 TCP 接收窗口大小。 可以使用 SO_RCVBUF 随时增加套接字的 TCP 接收窗口大小,但只能在建立连接之前减小。 若要使用窗口缩放,在使用 SO_RCVBUF 套接字选项时,应用程序必须指定大于 65,535 字节的窗口大小,然后才能建立连接。
TCP 接收窗口大小的理想值通常难以确定。 为了填充发送方和接收方之间的网络容量,接收窗口大小应设置为连接的带宽延迟乘积,即带宽乘以往返时间。 即使应用程序可以正确确定带宽延迟积,也不知道接收应用程序从传入数据缓冲区检索数据的速度 (应用程序检索速率) 。 尽管支持 TCP 窗口缩放,但 Windows Server 2003 和 Windows XP 中的最大接收窗口大小仍可限制吞吐量,因为它是所有 TCP 连接 (的固定最大大小,除非使用 SO_RCVBUF) 为每个应用程序指定,否则这会提高某些连接的吞吐量,降低其他连接的吞吐量。 此外,TCP 连接的固定最大接收窗口大小不会随网络条件的变化而变化。
为了解决基于网络当前条件正确确定 TCP 连接的最大接收窗口大小值的问题,Windows Vista 中的 TCP/IP 堆栈支持接收窗口自动优化功能。 启用此功能后,接收窗口自动优化通过测量带宽延迟积和应用程序检索速率持续确定最佳真实接收窗口大小,并根据不断变化的网络条件调整真正的最大接收窗口大小。 接收窗口自动优化默认启用 TCP WSopt 扩展,允许最多 16,776,960 个字节用于真正的窗口大小。 当数据通过连接流动时,TCP/IP 堆栈会监视连接,测量连接的当前带宽延迟乘积和应用程序接收速率,并调整实际接收窗口大小以优化吞吐量。 TCP/IP 堆栈根据网络条件更改 TCP 标头中 Window 字段的值,因为 WSopt 缩放因子在首次建立连接时是固定的。
Windows Vista 中的 TCP/IP 堆栈不再使用 TCPWindowSize 注册表值。 由于 TCP 对等机之间的吞吐量更高,数据传输期间网络带宽的利用率会提高。 如果所有应用程序都经过优化以接收 TCP 数据,则网络的整体利用率可能会大幅提高,这使得服务质量 (QoS 的使用在以或接近容量运行的网络上) 更重要。
未使用 WsaBehaviorReceiveBuffering 指定SIO_SET_COMPATIBILITY_MODE时,Windows Vista 上接收缓冲的默认行为是在建立连接后,不允许使用 SO_RCVBUF 套接字选项减小接收窗口大小。
未使用 WsaBehaviorAutoTuning 指定SIO_SET_COMPATIBILITY_MODE时,Windows Vista 上自动优化的默认行为是堆栈将使用窗口比例系数 8 进行接收窗口自动优化。
请注意,如果应用程序使用 SO_RCVBUF 套接字选项设置有效的接收窗口大小,则堆栈将使用指定的大小,并且窗口接收自动优化将禁用。
也可以使用以下命令完全禁用 Windows 自动调整,在这种情况下, netsh interface tcp set global autotuninglevel=disabled
指定 WsaBehaviorAutoTuning 将不起作用。
还可以根据 Windows Server 2008 上设置的组策略禁用窗口接收自动调整。
对于某些 Internet 网关设备和防火墙,Windows Vista 上需要 WsaBehaviorAutoTuning 选项,这些设备和防火墙无法正确支持使用 WSopt 扩展和 Windows 缩放因子的 TCP 连接数据流。 在 Windows Vista 上,接收方默认协商窗口比例系数为 8,最大真实窗口大小为 16,776,960 字节。 当数据开始在快速链接上流动时,Windows 最初从 64 Kb true 窗口大小开始,方法是将 TCP 标头的 Window 字段设置为 256,并在 TCP 选项中将窗口比例系数设置为 8 (256*2^8=64KB) 。 某些 Internet 网关设备和防火墙忽略窗口缩放因子,仅查看 TCP 标头中指定为 256 的播发窗口字段,并删除包含超过 256 字节 TCP 数据的连接的传入数据包。 若要支持 TCP 接收窗口缩放,网关设备或防火墙必须监视 TCP 握手,并跟踪作为 TCP 连接数据的一部分的协商窗口缩放因子。 此外,其他平台上的某些应用程序和 TCP 堆栈实现会忽略 TCP WSopt 扩展和窗口缩放因子。 因此,发送数据的远程主机可能会以 TCP 标头的 Window 字段中播发的速率发送数据 (256 字节) 。 这可能会导致接收方接收数据的速度非常慢。
将 BehaviorId 成员设置为 WsaBehaviorAutoTuning 并将 TargetOsVersion 设置为 Windows Vista 会将窗口缩放比例降低到 2,因此 TCP 标头中的 Window 字段最初设置为 16,384 字节,而初始真实窗口接收大小为 64K 字节的窗口缩放因子设置为 2。
然后,窗口自动优化功能可以通过将 TCP 标头中的 Window 字段设置为 65,535 字节,将真正的窗口接收大小增加到 262,140 字节。
创建套接字后,应用程序应立即设置 SIO_SET_COMPATIBILITY_MODE IOCTL,因为此选项在发送 SYN 后没有意义或不适用。
设置此选项的影响与以下命令相同: netsh interface tcp set global autotuninglevel=highlyrestricted
请注意, Mswsockdef.h 头文件自动包含在 Mswsock.h 或 Netiodef.h 中,不应直接使用。