カスタム ストリームのアップグレード
TCP、名前付きパイプなど、ストリーム指向のデータ伝送機構 (トランスポート) が扱うのは、クライアントとサーバーの間を流れる、連続的なバイト ストリームです。 このストリームは、Stream オブジェクトによって実現されます。 ストリーム アップグレードでは、クライアントは、オプションのプロトコル階層をチャネル スタックに追加する場合に、相手側の通信チャネルにも同じことをするよう要求します。 ストリーム アップグレードは、Stream オブジェクトをアップグレードされたものに置き換える形で実施します。
たとえば、トランスポート ストリームのすぐ上に圧縮ストリームを作成することができます。 この場合、元のトランスポート Stream を、それを圧縮 Stream でラップしたものに置き換えます。
オブジェクトを順にラップしていくことにより、ストリーム アップグレードを多重に適用できます。
ストリーム アップグレードの動作
ストリーム アップグレード処理には 4 つのコンポーネントが関与します。
イニシエーターは、必要な処理を起動するコンポーネントです。実行時に、接続先に対して、同じようにチャネル トランスポート層をアップグレードするよう要求する役割があります。
アクセプタは実際にアップグレードを行うコンポーネントです。接続先からのアップグレード要求を受け取り、可能であれば、実際にアップグレードする役割があります。
プロバイダーは、クライアント上にイニシエーター、サーバー上にアクセプタを生成するコンポーネントです。
"バインディング要素" は、サービスやクライアントのバインディングに追加され、実行時にプロバイダーを生成するコンポーネントです。
なお、多重にアップグレードを適用する場合、イニシエーターとアクセプタはステート マシンをカプセル化して、適切な適用順序になるようにします。
ストリーム アップグレードの実装方法
Windows Communication Foundation (WCF) には、実装できる次の 4 つの abstract
クラスが用意されています。
カスタム ストリーム アップグレードを実装する手順を以下に示します。 これは、クライアント側、サーバー側双方に、ごく単純なストリーム アップグレード処理を組み込む場合の手順です。
StreamUpgradeInitiator を実装するクラスを作成します。
InitiateUpgrade メソッドをオーバーライドして、ストリームを入力すると、それをアップグレードしたストリームが返されるようにします。 これは同期型のメソッドですが、これに似た非同期型のメソッドもあります。
GetNextUpgrade メソッドをオーバーライドして、追加のアップグレードがないか確認するようにします。
StreamUpgradeAcceptor を実装するクラスを作成します。
AcceptUpgrade メソッドをオーバーライドして、ストリームを入力すると、それをアップグレードしたストリームが返されるようにします。 これは同期型のメソッドですが、これに似た非同期型のメソッドもあります。
CanUpgrade メソッドをオーバーライドして、アップグレード処理中のこの時点で、このアップグレード アクセプタがアップグレード要求に応じることができるかどうかを判断するようにします。
StreamUpgradeProvider を実装するクラスを作成します。 CreateUpgradeAcceptor メソッドおよび CreateUpgradeInitiator メソッドをオーバーライドして、手順 1. および 2. で定義したアクセプタとイニシエーターのインスタンスをそれぞれ返すようにします。
StreamUpgradeBindingElement を実装するクラスを作成します。
クライアント側の BuildClientStreamUpgradeProvider メソッドとサービス側の BuildServerStreamUpgradeProvider メソッドをオーバーライドします。
クライアント側の BuildChannelFactory メソッドとサービス側の BuildChannelListener メソッドをオーバーライドして、アップグレード バインド要素を BindingParameters に追加するようにします。
サーバー側とクライアント側のバインディングに、新しいストリーム アップグレード バインド要素を追加します。
セキュリティ アップグレード
ストリーム アップグレードの特別な場合として、セキュリティ アップグレードがあります。
WCF には既に、セキュリティに関連するストリーム アップグレードを実装するためのバインディング要素が 2 つ組み込まれています。 トランスポート レベルのセキュリティ構成は、WindowsStreamSecurityBindingElement および SslStreamSecurityBindingElement にカプセル化されており、これらの要素を構成して、カスタム バインドに追加することができます。 この 2 つのバインド要素は、クライアント側およびサーバー側のストリーム アップグレード プロバイダーを構築する StreamUpgradeBindingElement クラスを拡張したものです。 これらのバインド要素には、セキュリティ ストリーム アップグレード専用のプロバイダー クラスを作成するメソッドが定義されています。これらのメソッドは public
ではないので、いずれの場合もバインド要素をバインディングに追加するだけでセキュリティ アップグレードが可能です。
上記の 2 つのバインド要素では対応できないセキュリティ上の要求に備え、既述のイニシエーター、アクセプタ、プロバイダーの各基底クラスから派生した abstract
クラスが 3 つ定義されています。
セキュリティ ストリーム アップグレードを実装する手順も、以上 3 つのクラスから派生することを除き、一般のストリーム アップグレードと同様です。 これらのクラスには実行時にセキュリティ情報をやり取りするためのプロパティが追加されているので、これをオーバーライドしてください。
多重アップグレード
追加のアップグレード要求を作成するには、前述の手順を繰り返して、追加の StreamUpgradeProvider およびバインド要素の拡張を作成し、 これをバインディングに追加します。 各バインド要素は、バインディングに追加した順に処理されます。 各アップグレード プロバイダーは、BuildChannelFactory および BuildChannelListener で、既存のアップグレード バインディング パラメーターに、どのように自分自身を積み重ねるかを指定できます。 次に、既存のアップグレード バインディング パラメーターを、新しい複合アップグレード バインディング パラメーターに置き換えます。
あるいは、単一のアップグレード プロバイダーで、多重のアップグレードに対応することも可能です。 たとえば、セキュリティと圧縮の両方に対応するカスタム ストリーム アップグレード プロバイダーを実装できます。 手順は次のとおりです。
StreamSecurityUpgradeProvider のサブクラスとして、イニシエーターおよびアクセプタを生成するプロバイダー クラスを作成します。
StreamSecurityUpgradeInitiator のサブクラスを作成し、GetNextUpgrade メソッドをオーバーライドして、圧縮ストリーム、セキュリティ ストリームの順にコンテンツ タイプを返すようにします。
StreamSecurityUpgradeAcceptor のサブクラスを作成し、CanUpgrade メソッドをオーバーライドして、独自のコンテンツ タイプに応じた処理をするようにします。
ストリームは、GetNextUpgrade および CanUpgrade をそれぞれ呼び出した後にアップグレードされます。