接続要求の受け入れ
アプリケーションが WSAAccept、accept、または AcceptEx 関数を呼び出してソケットの着信接続要求を受け入れる場合、Windows ソケット スイッチは常にこの呼び出しを TCP/IP サービス プロバイダーに転送します。 受信接続要求が SAN 以外のネットワークから到着した場合は、NDIS パスを通過し、TCP/IP サービス プロバイダーが処理します。 接続要求が SAN 上のリモート ピアから到着した場合、接続要求を受け入れるかどうかを判断したり、アプリケーションの WSAAccept、accept、または AcceptEx 関数を完了したりする際に、スイッチは TCP/IP サービス プロバイダーと SAN サービス プロバイダー間の仲介役として機能します。
次の図は、受信接続要求を受け入れるか拒否するかを決定する際の Windows ソケット スイッチと SAN サービス プロバイダー間の相互作用の概要を示しています。 以下のシーケンスとセクションでは、受け入れの決定について詳しく説明します。
接続要求を受け入れる、または拒否するには
リモート ピアからの受信接続要求を受信すると、SAN サービス プロバイダーは、「SAN での接続のリッスン」で 説明されているように、イベント オブジェクトを通知します。
Windows ソケット スイッチは、SAN サービス プロバイダーの WSPEnumNetworkEvents 関数を呼び出して、FD_ACCEPT イベント コードを受信します。
FD_ACCEPT イベント コードを受信すると、スイッチは SAN サービス プロバイダーの WSPAccept 関数を呼び出して、受信接続要求を受け入れるか拒否します。
スイッチが SAN サービス プロバイダーの WSPAccept 関数を呼び出すときに、スイッチは条件関数を指定します。 SAN サービス プロバイダーは、WSPAccept の呼び出しから戻る前に、WSPAccept 関数が呼び出されたのと同じスレッドでこの条件関数を呼び出す必要があります。
スイッチは、この条件関数から CF_ACCEPT または CF_REJECT コードを返して、それぞれ接続要求の受け入れ、または拒否を示します。
接続要求の受け入れと受け入れソケットの作成
アプリケーションが受信接続要求を受け入れた場合、スイッチは、スイッチの条件関数を完了するために、CF_ACCEPT コードを SAN サービス プロバイダーに返します。 CF_ACCEPT を受信すると、SAN サービス プロバイダーは、受け入れソケットに関する情報を格納する内部データ構造を初期化します。 SAN サービス プロバイダーの WSPAccept 関数は、次に WPUCreateSocketHandle 関数を呼び出して、スイッチから受け入れソケットの記述子を取得する必要があります。 SAN サービス プロバイダーは、受け入れソケットの内部データ構造にスイッチの記述子を格納し、WSPAccept 呼び出しを完了するために受け入れソケット用の独自の記述子を返す必要があります。 スイッチは、SAN サービス プロバイダーの関数を呼び出すときに受け入れソケットの SAN サービス プロバイダーの内部記述子を提供する必要があります。一方、SAN サービス プロバイダーは、スイッチの呼び出しでスイッチのソケット記述子を提供する必要があります。
WSPAccept を正常に完了する前に、SAN サービス プロバイダーは Win32 ResetEvent 関数を呼び出してイベント オブジェクトをリセットする必要があります。 これにより、SAN サービス プロバイダーは後で Win32 SetEvent 関数を呼び出して、次の受信接続要求を受け入れるようにスイッチに通知できます。
接続要求の拒否
アプリケーションが受信接続要求を拒否した場合、スイッチは、スイッチの条件関数を完了するために、CF_REJECT コードを SAN サービス プロバイダーに返します。 CF_REJECT を受信すると、SAN サービス プロバイダーは WSAECONNREFUSED エラー コードをスイッチに返して WSPAccept 呼び出しを完了する必要があります。
リモート ピアへの接続要求の受け入れまたは拒否を示す
SAN サービス プロバイダーは、リモート ピアの接続要求を受け入れるか拒否することをリモート ピアに示す前に、スイッチの条件関数を呼び出す必要があります。 スイッチの条件関数が返す値に応じて、SAN サービス プロバイダーはリモート ピアに対して次のいずれかの指示を行う必要があります。
スイッチの条件関数が CF_ACCEPT を返した場合、SAN サービス プロバイダーは、リモート ピアの接続要求の受け入れを示す必要があります。 その後、リモート ピアの SAN サービス プロバイダーは、WSPConnect の呼び出しによって開始された接続操作を正常に完了できます。
スイッチの条件関数が CF_REJECT を返した場合、SAN サービス プロバイダーは、リモート ピアの接続要求の拒否を示す必要があります。 その後、リモート ピアの SAN サービス プロバイダーは、WSAECONNREFUSED エラー コードを使用して WSPConnect 呼び出しによって開始された接続操作を失敗させる必要があります。
セッションのネゴシエーション
スイッチが SAN サービス プロバイダーを正常に使用してリモート ピアからの接続要求を受け入れると、スイッチはそのピアとのセッションをネゴシエートします。
セッションをネゴシエートするには
リモート ピアのスイッチは、SAN サービス プロバイダーの WSPRecv 関数を呼び出して、一連の受信バッファーをポストします。
リモート ピアのスイッチは、SAN サービス プロバイダーの WSPSend 関数を呼び出して、ローカルの受け入れエンドポイントにあるスイッチにセッション ネゴシエーション メッセージを送信します。 このメッセージには、リモート ピアのスイッチがポストした受信バッファーの数が含まれます。
ローカル受け入れエンドポイントのスイッチは、ローカル SAN サービス プロバイダーの WSPRecv 関数を呼び出して独自の受信バッファーをポストしますが、セッション ネゴシエーション メッセージを受信するために時間内に実行できない場合があります。 ローカル スイッチが受信バッファーを時間内にポストせず、基になる NIC がフロー制御をサポートしていない場合、ローカル受け入れエンドポイントの SAN サービス プロバイダーは、リモート スイッチのセッション ネゴシエーション メッセージを独自のプライベート受信バッファーにバッファーする必要があります。 スイッチが受信バッファーをポストすると、SAN サービス プロバイダーは、プライベート バッファーからスイッチ バッファーにすべてのデータがコピーされるまで、そのプライベート受信バッファーからスイッチ バッファーにデータを 1 対 1 でコピーします。
SAN サービス プロバイダーは、後続のスイッチ バッファーで通常の受信処理を実行します。つまり、そのようなすべてのスイッチ バッファーを NIC の受信キューにポストします。
セッション ネゴシエーション メッセージが到着する前にスイッチが受信バッファーをポストしなかったため、SAN サービス プロバイダーは接続を中断できません。 セッション ネゴシエーション メッセージの最大長は 256 バイトです。
ローカル受け入れエンドポイントのスイッチは、セッション ネゴシエーション メッセージに応答する前に受信バッファーをポストします。 ローカル スイッチは、セッション ネゴシエーション メッセージに応答するために、ローカル SAN サービス プロバイダーの WSPSend 関数を呼び出します。 ローカル スイッチの応答には、ローカル スイッチがポストした受信バッファーの数が含まれます。 この時点から、ローカル スイッチは、ポストされた受信バッファーのセットが、接続に到着したメッセージを受信するのに十分なサイズであることを保証します。
アプリケーションが AcceptEx の呼び出しで初期受信バッファーを指定した場合、スイッチは、アプリケーションの AcceptEx 呼び出しを完了する前に、リモート ピアから最初のデータ メッセージを受信するまで待機します。
アプリケーションが独自の accept 呼び出しを取り消すと、スイッチは適切な SAN サービス プロバイダーの WSPCloseSocket 関数を呼び出して、受け入れる SAN ソケットを閉じます。