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

出力バッファーのサイズ (バイト単位)。 このパラメーターは 0 に設定する必要があります。

lpcbBytesReturned

出力バッファーに格納されているデータのサイズ (バイト単位) を受け取る変数へのポインター。 この返されたパラメーターは、出力がないため、この操作の DWORD 値 0 を指します。

lpvOverlapped

WSAOVERLAPPED 構造体へのポインター。

重複する属性なしでソケット s が作成された場合、 lpOverlapped パラメーターは無視されます。

重複した属性を使用して s を開き、 lpOverlapped パラメーターが NULL でない場合、操作は重複 (非同期) 操作として実行されます。 この場合、 lpOverlapped パラメーターは有効な WSAOVERLAPPED 構造体を指している必要があります。

重複する操作の場合、 WSAIoctl または WSPIoctl 関数は直ちに戻り、操作が完了すると適切な完了メソッドが通知されます。 それ以外の場合、関数は操作が完了するかエラーが発生するまで戻りません。

lpCompletionRoutine

種類: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

操作が完了したときに呼び出される完了ルーチンへのポインター (重複していないソケットの場合は無視されます)。

lpThreadId

WPUQueueApc への後続の呼び出しでプロバイダーによって使用される WSATHREADID 構造体へのポインター。 プロバイダーは、WPUQueueApc 関数が戻るまで、参照先の WSATHREADID 構造体 (同じへのポインターではありません) を格納する必要があります。

メモ このパラメーターは 、WSPIoctl 関数にのみ適用されます。

lpErrno

エラー コードへのポインター。

メモ このパラメーターは 、WSPIoctl 関数にのみ適用されます。

戻り値

操作が正常に完了すると、 WSAIoctl または WSPIoctl 関数は 0 を返します。

操作が失敗した場合、または保留中の場合、 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 ソケット s が接続されていません。
WSAENOTSOCK 記述子 s はソケットではありません。
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構造体で指定されます。 cbInBuffer パラメーターには、WSA_COMPATIBILITY_MODE構造体へのポインターが渡されます。 この構造体は次のように定義されます。

// 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 ウィンドウのスケーリング オプションも無効になっており、真の受信ウィンドウの最大サイズは 65,535 バイトに制限されています。 接続が確立される前に 65,535 バイトを超える値を指定して、このソケットで SO_RCVBUF ソケット オプションが呼び出された場合でも、TCP ウィンドウスケーリング オプションを接続でネゴシエートすることはできません。

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 パケット ヘッダーのウィンドウ フィールド) を使用して、受信ウィンドウ のサイズを送信者に報告します。 したがって、使用できる最大のウィンドウは 65,535 バイトです。 この制限を回避するために、65,535 バイトを超えるウィンドウを許可する高パフォーマンス TCP 用に TCP 拡張オプション TCP ウィンドウ スケールが追加されました。 TCP ウィンドウ スケール オプション (WSopt) は、 IETF Web サイトで利用可能な RFC 1323 で定義されています。 WSopt 拡張機能は、1 バイトの対数スケール ファクターを使用して TCP ウィンドウの定義を 32 ビットに拡張し、TCP ヘッダーの 16 ビット Window フィールドを拡張します。 WSopt 拡張機能は、暗黙的なスケール ファクター (2 から何らかの電力) を定義します。これは、TCP ヘッダーで見つかったウィンドウ サイズ値を乗算して、実際のウィンドウ サイズを取得するために使用されます。 そのため、ウィンドウスケールファクター8は、TCPヘッダーのウィンドウフィールドの値に2^8または256を掛けた値と等しい真のウィンドウサイズになります。 したがって、TCP ヘッダーの Window フィールドが最大値 65,535 バイトに設定され、WSopt スケール ファクターが 8 の値にネゴシエートされた場合、実際のウィンドウ サイズは 16,776,960 バイトになります。

true の受信ウィンドウ サイズであるため、スケール ファクターは最大受信バッファー領域によって決まります。 この最大バッファー領域は、TCP 受信側が受信確認を待機する前に TCP 送信者が送信できるデータの量です。 接続が確立されると、受信ウィンドウ サイズは各 TCP セグメント (TCP ヘッダーの [ウィンドウ] フィールド) でアドバタイズされます。 送信者が送信できるデータの最大量をアドバタイズすることは、受信側が格納できないデータを送信者が送信できないようにする受信側フロー制御メカニズムです。 送信側ホストは、受信確認と受信ウィンドウ サイズの更新を待機する前に、受信側によってアドバタイズされたデータの最大量のみを送信できます。

Windows Server 2003 および Windows XP では、TCP/IP スタックの受信ウィンドウ サイズを表す最大受信バッファー領域には、送信インターフェイスのリンク速度に基づく既定値があります。 実際の値は、TCP 接続の確立中にネゴシエートされた最大セグメント サイズ (MSS) の増分に自動的に調整されます。 そのため、10 Mbit/秒のリンクの場合、既定の受信ウィンドウ サイズは通常 16K バイトに設定されますが、100 MBit/秒のリンクでは、既定の受信ウィンドウ サイズは 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

TCPWindowSize のレジストリ値は、WSopt 拡張機能を使用しない場合は最大 65,535 バイト、WSopt 拡張機能を使用する場合は最大 1,073,741,823 バイトに設定できます (最大スケール ファクター 4 がサポートされます)。 ウィンドウ スケーリングを使用しない場合、アプリケーションでは、パス帯域幅に関係なく、100 ミリ秒のラウンドトリップ時間 (RTT) を使用して、パスで約 5 メガビット/秒 (Mbps) のスループットのみを実現できます。 このスループットは、ウィンドウスケーリングを使用してギガビット/秒 (Gbps) 経由でにスケーリングできます。これにより、TCP は接続の確立中にウィンドウ サイズのスケーリング係数をネゴシエートできます。

Windows Server 2003 および Windows XP では、WSopt 拡張機能を有効にするには、次のレジストリ値を設定します。

HKEY_LOCAL_MACHINE\SYSTEM\Current Control Set\Services\Tcpip\Parameters\Tcp1323Opts

Tcp1323Opts レジストリ値は、ビット 0 が設定されると TCP WSopt 拡張機能が有効になるように DWORD でエンコードされます。 ビット 1 を設定すると、RFC 1323 で定義されている TCP Timestamp オプション (TSopt) が有効になります。 そのため、1 または 3 のいずれかの値を指定すると、WSopt 拡張機能が有効になります。

Windows Server 2003 および Windows XP では、既定値は TCPWindowSize と Tcp1323Opts レジストリ値が作成されないことです。 そのため、既定では、WSopt 拡張機能が無効になり、TCP 受信ウィンドウ サイズが、リンク速度に基づいて最大 65,535 バイトの最大値にシステムによって設定されます。 Windows Server 2003 と Windows XP で Tcp1323Opts レジストリ値を設定してウィンドウスケーリングを有効にすると、TCP 接続でのウィンドウスケーリングは、送信側と受信側の両方が、ウィンドウスケールファクターをネゴシエートするために相互に送信される同期 (SYN) セグメントに TCP ウィンドウスケールオプションを含める場合にのみ使用されます。 接続でウィンドウのスケーリングを使用する場合、TCP ヘッダーの Window フィールドは 65,535 バイトに設定され、ウィンドウ スケール ファクターを使用して、接続の確立時にネゴシエートされたウィンドウ スケール ファクターによって、真の受信ウィンドウ サイズを上方向に調整します。

アプリケーションでは、 SO_RCVBUF ソケット オプションを使用して、接続の TCP 受信ウィンドウ サイズを指定できます。 ソケットの TCP 受信ウィンドウ サイズは、 SO_RCVBUFを使用していつでも増やすことができますが、接続を確立する前にのみ減らすことができます。 ウィンドウのスケーリングを使用するには、接続が確立される前に 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=disabledWsaBehaviorAutoTuning を指定しても影響はありません。 Windows Server 2008 で設定されたグループ ポリシーに基づいて、ウィンドウ受信の自動チューニングを無効にすることもできます。

WSopt 拡張機能と Windows スケール ファクターを使用する TCP 接続のデータ フローを正しくサポートしていない一部のインターネット ゲートウェイ デバイスとファイアウォールでは、Windows Vista で WsaBehaviorAutoTuning オプションが必要です。 Windows Vista では、受信者は既定で 8 のウィンドウ スケール ファクターをネゴシエートし、最大の true ウィンドウ サイズは 16,776,960 バイトです。 データが高速リンクで流れ始めると、Windows は最初に TCP ヘッダーの Window フィールドを 256 に設定し、TCP オプションでウィンドウ スケール ファクターを 8 に設定することで、64 キロバイトの true ウィンドウ サイズで始まります (256*2^8=64 KB)。 一部のインターネット ゲートウェイ デバイスとファイアウォールでは、ウィンドウ スケール ファクターが無視され、256 として指定された TCP ヘッダーのアドバタイズされた Window フィールドのみを確認し、256 バイトを超える TCP データを含む接続の受信パケットをドロップします。 TCP 受信ウィンドウのスケーリングをサポートするには、ゲートウェイ デバイスまたはファイアウォールで TCP ハンドシェイクを監視し、TCP 接続データの一部としてネゴシエートされたウィンドウ スケール ファクターを追跡する必要があります。 また、他のプラットフォーム上の一部のアプリケーションと TCP スタックの実装では、TCP WSopt 拡張機能とウィンドウ スケーリング 係数が無視されます。 そのため、データを送信するリモート ホストは、TCP ヘッダーの [ウィンドウ] フィールドにアドバタイズされた速度 (256 バイト) でデータを送信できます。 これにより、受信側によってデータの受信が非常に遅くなる可能性があります。

BehaviorId メンバーを WsaBehaviorAutoTuning に設定し、TargetOsVersion を Windows Vista に設定すると、ウィンドウ スケール ファクターが 2 に減少するため、TCP ヘッダーの Window フィールドは最初は 16,384 バイトに設定され、最初の true ウィンドウ受信サイズは 64K バイトの場合、ウィンドウ スケール ファクターは 2 に設定されます。 ウィンドウの自動チューニング機能では、TCP ヘッダーの Window フィールドを 65,535 バイトに設定することで、true ウィンドウの受信サイズを最大 262,140 バイトまで増やすことができます。 アプリケーションでは、ソケットが作成されるとすぐに SIO_SET_COMPATIBILITY_MODE IOCTL を設定する必要があります。これは、SYN の送信後にこのオプションが意味をなさないか適用されないためです。 このオプションを設定すると、次のコマンドと同じ影響があります。 netsh interface tcp set global autotuninglevel=highlyrestricted

Mswsockdef.h ヘッダー ファイルは Mswsock.h または Netiodef.h に自動的に含まれるので、直接使用しないでください。

こちらもご覧ください

ソケット

WSAGetLastError

WSAGetOverlappedResult

WSAIoctl

WSAOVERLAPPED

WSASocketA

WSASocketW