次の方法で共有


シンクとシンク チェーン

このトピックの対象は、既存のアプリケーションとの下位互換性のために残されているレガシ テクノロジに特定されています。新規の開発には、このトピックを適用しないでください。分散アプリケーションは、現在は Windows Communication Foundation (WCF) を使用して開発する必要があります。

クライアントはメッセージをリモート アプリケーション ドメインに送信することによって、リモート オブジェクトのメソッド呼び出しを行います。これは、チャネル オブジェクトのセットによって実行されます。クライアント アプリケーション ドメインにはクライアント チャネルがあり、リモート アプリケーション ドメインにはリモート チャネルがあります。各チャネルは、チェーンで互いにリンクされている一連のチャネル シンクで構成されます。基本的なチャネル シンク チェーンの構造を次の図に示します。

シンクとシンク チェーン

チャネルは、メッセージの送信前または受信後に、チャネル シンク オブジェクトのチェーンに各メッセージを送信します。このシンク チェーンには、フォーマッタ シンク、トランスポート シンク、スタックビルダー シンクなどの、基本的なチャネル機能に必要なシンクが含まれています。チャネル シンク チェーンをカスタマイズして、メッセージまたはストリームで特別なタスクを実行することもできます。各チャネル シンクは、IClientChannelSink または IServerChannelSinkfrlrfSystemRuntimeRemotingChannelsIServerChannelSinkClassTopic を実装します。クライアント側の最初のチャネル シンクは、IMessageSinkfrlrfSystemRuntimeRemotingMessagingIMessageSinkClassTopic も実装する必要があります。このシンクは通常、IMessageSinkIChannelSinkBase、および IClientChannelSink から継承する IClientFormatterSink を実装し、受信メッセージをストリーム (IMessagefrlrfSystemRuntimeRemotingMessagingIMessageClassTopic オブジェクト) に変換するため、フォーマッタ シンクと呼ばれます。

チャネル シンク チェーンは、アプリケーション ドメインに対して送信されたすべてのメッセージ、またはアプリケーション ドメインから送信されたすべてのメッセージを処理します。チャネル シンクは処理されているメッセージにアクセスでき、以降の処理では、処理後にシステムに返されたメッセージが使用されます。チャネル シンク チェーンは、ログ サービスや任意の種類のフィルターを実装するのに適した場所です。

各チャネル シンクはストリームを処理し、そのストリームを次のチャネル シンクに渡すため、特定のシンクの前後にあるシンクは、渡されたストリームの処理方法について情報を持っている必要があります。

tdzwhfy3.note(ja-jp,VS.100).gif注 :
メッセージ シンクが例外をスローすることはありません。メッセージ シンクがこれを制御する方法の 1 つは、try ブロックから catch ブロックまでのメソッド コードをラップすることです。

.NET リモート処理メッセージを処理するチャネル シンクを作成するのは、チャネル シンク プロバイダー (IClientChannelSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientChannelSinkProviderClassTopicIClientFormatterSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientFormatterSinkProviderClassTopicIServerChannelSinkProvider の各インターフェイスを実装するオブジェクト) です。リモート型がアクティブになると、チャネルからチャネル シンク プロバイダーが取得され、シンク プロバイダー上で CreateSink メソッドが呼び出されて、チェーンから最初のチャネル シンクが取得されます。

チャネル シンクは、クライアントとサーバー間でメッセージを転送します。チャネル シンクは、チェーン内で互いにリンクされています。CreateSink メソッドは、呼び出されたときに以下の処理を行います。

  • チャネル シンクを作成します。

  • チェーン内の次のシンク プロバイダーで CreateSink を呼び出します。

  • 次のシンクと現在のシンクが互いにリンクされるようにします。

  • そのシンクを呼び出し元に返します。

チャネル シンクは、シンク上で行われたすべての呼び出しをチェーン内の次のシンクに転送します。また、次のシンクへの参照を格納するための機構を提供します。

チャネル シンクには、シンク チェーン内で転送する内容について、高い柔軟性があります。たとえば、シリアル化された元のメッセージを送信する前に認証をネゴシエートするセキュリティ シンクは、完全なチャネル メッセージを保持し、コンテンツ ストリームをシンク自身の内容に置き換え、シンク チェーンを通じてリモート アプリケーション ドメインまで送信できます。逆方向の処理では、セキュリティ シンクがリモート アプリケーション ドメイン内の対応するセキュリティ シンクとの間で通信を確立して、応答メッセージを受け取ることができます。合意に到達すると、送信元のセキュリティ シンクは元のコンテンツ ストリームをリモート アプリケーション ドメインに送信できます。

チャネル シンク チェーンでのメッセージ処理

メッセージを処理できるチャネルを .NET リモート処理システムが見つけると、このチャネルは

SyncProcessMessage (または AsyncProcessMessage) を呼び出して、メッセージをフォーマッタ チャネル シンクに渡します。フォーマッタ シンクはトランスポート ヘッダー配列を作成し、次のシンク上に GetRequestStream を呼び出します。この呼び出しは、シンク チェーン内で転送され、フォーマッタ シンクに戻される要求ストリームを任意のシンクで作成できます。GetRequestStreamnull 参照 (Visual Basic の場合は Nothing) を返した場合、フォーマッタ シンクはシリアル化に使用する独自のシンクを作成します。この呼び出しが返されると、メッセージはシリアル化され、シンク チェーンの最初のチャネル シンクで適切なメッセージ処理メソッドが呼び出されます。

シンクは、ストリームにデータを書き込むことはできませんが、ストリームからデータを読み込んだり、必要に応じて新しいストリームを渡したりできます。また、シンクはヘッダー配列にヘッダーを追加したり (以前に次のシンク上に GetRequestStream を呼び出していない場合)、シンク自体をシンク スタックに追加した後にこの呼び出しを次のシンクに転送したりできます。同期スタックを使用することによって、非同期呼び出しの完了時に、非同期呼び出しから呼び出し元にコールバックできます。呼び出しがチェーンの末尾にあるトランスポート シンクに到達すると、トランスポート シンクはヘッダーとシリアル化されたメッセージをチャネル経由でサーバーに送信します。サーバーでは処理全体が逆になります。サーバー側のトランスポート シンクがヘッダーとシリアル化されたメッセージをストリームのサーバー側から取得し、フォーマッタ シンクに到達するまで、これらをシンク チェーンを通じて転送します。フォーマッタ シンクはメッセージを逆シリアル化し、.NET リモート処理システムに転送します。.NET リモート処理システムでは、メッセージが元のメソッドの呼び出しに変換され、サーバー オブジェクト上で呼び出されます。

チャネル シンク チェーンの作成

新しいチャネル シンクを作成するには、.NET リモート処理システムを実装および構成して、IServerChannelSinkProvider 実装または IClientChannelSinkProvider 実装を認識するようにする必要があります。これにより、カスタム IClientChannelSink やカスタム IServerChannelSink の実装を作成したり、チェーン内の次のシンクを取得したりできます。カスタム チャネル シンクを実装する場合は、BaseChannelSinkWithProperties 抽象クラスを使用すると便利です。

チャネル シンク プロバイダーの構築

アプリケーションは、チャネルの構築時に、サーバー チャネル シンク プロバイダーまたはクライアント チャネル シンク プロバイダーをパラメーターとして指定できます。チャネル シンク プロバイダーはチェーン内に格納する必要があります。開発者は、外部のチャネル シンク プロバイダーがチャネル コンストラクターに渡される前に、すべてのチャネル シンク プロバイダーを 1 つのチェーンにまとめておく必要があります。チャネル シンク プロバイダーは、この目的のために Next プロパティを実装します。クライアント側のチャネル シンク プロバイダーを構築する方法を、次のコード例に示します。コード例の全体については、「リモート処理の例: チャネル シンク プロバイダー」を参照してください。

private Function CreateDefaultClientProviderChain() As IClientChannelSinkProvider
   Dim chain As New FirstClientFormatterSinkProvider            
   Dim sink As IClientChannelSinkProvider
   sink = chain
   sink.Next = New SecondClientFormatterSinkProvider
   sink = sink.Next
   return chain
End Function 
private IClientChannelSinkProvider CreateDefaultClientProviderChain(){
   IClientChannelSinkProvider chain = new FirstClientFormatterSinkProvider();            
   IClientChannelSinkProvider sink = chain;
   sink.Next = new SecondClientFormatterSinkProvider();
   sink = sink.Next;
   return chain;
} 
tdzwhfy3.note(ja-jp,VS.100).gif注 :
構成ファイルで複数のチャネル シンク プロバイダーが指定されている場合、.NET リモート処理システムは、構成ファイルに記述されている順序でプロバイダーをチェーンします。チャネル シンク プロバイダーは、Configure の呼び出し中にチャネルが作成されるときに作成されます。

フォーマッタ シンク

フォーマッタ シンクは、チャネル メッセージをシリアル化し、IMessage を実装するオブジェクトとしてメッセージ ストリームに変換します。一部のフォーマッタ シンクの実装では、システムによって提供されるフォーマッタ型 (BinaryFormatterfrlrfSystemRuntimeSerializationFormattersBinaryBinaryFormatterClassTopic および SoapFormatterfrlrfSystemRuntimeSerializationFormattersSoapSoapFormatterClassTopic) を使用します。その他の実装では、独自の方法を使用してチャネル メッセージをストリームに変換できます。

フォーマッタ シンクは、必要なヘッダーを生成し、ストリームにメッセージをシリアル化する機能を持ちます。フォーマッタ シンクの後は、SyncProcessMessage 呼び出しまたは AsyncProcessMessage 呼び出しを通じて、メッセージがシンク チェーン内のすべてのシンクに転送されます。この段階では、メッセージが既にシリアル化されており、変更できません。

tdzwhfy3.note(ja-jp,VS.100).gif注 :
メッセージを作成または変更する必要があるシンクは、シンク チェーンでフォーマッタの前に配置する必要があります。これは、IClientFormatterSink を実装し、システムに対してフォーマッタ シンクへの参照があると通知することで簡単に実行できます。その上で、実際のフォーマッタ シンクをシンク チェーン内の後続の位置に配置できます。

逆方向の処理を行うときは、フォーマッタ シンクがメッセージ ストリームを変換してチャネル メッセージのオブジェクト (戻りメッセージ) に戻します。クライアント側の最初のシンクは、IClientFormatterSink インターフェイスを実装する必要があります。CreateSink がチャネルに返されると、返された参照は SyncProcessMessage メソッドを呼び出せるように IClientFormatterSink 型にキャストされます。IClientFormatterSink は、IMessageSink から派生しています。キャストに失敗すると、システムで例外が発生します。

カスタム チャネル シンク

クライアント側では、フォーマッタ シンクと末尾のトランスポート シンクとの間にあるオブジェクトのチェーンに、カスタム チャネル シンクが挿入されます。クライアント チャネルまたはサーバー チャネルにカスタム チャネル シンクを挿入することにより、次のいずれかの時点で IMessage を処理できます。

  • メッセージとして表された呼び出しをストリームに変換し、ネットワーク経由で送信する処理の間。

  • ストリームがネットワークから取得され、サーバーのリモート オブジェクトの前にある最後のメッセージ シンク、またはプロキシ オブジェクト (クライアント側) に送信される処理の間。

カスタム シンクはストリームに対してデータを (呼び出しが送信か受信に応じて) 読み書きでき、必要な場合にはヘッダーに追加情報を追加できます。この段階では、メッセージがフォーマッタによって既にシリアル化されており、変更できません。メッセージ呼び出しがチェーンの末尾にあるトランスポート シンクに転送されると、トランスポート シンクはストリームにヘッダーを書き込み、チャネルで指定されたトランスポート プロトコルを使用して、ストリームをサーバー上のトランスポート シンクに転送します。

トランスポート シンク

トランスポート シンクは、クライアント側ではチェーンの最後に、サーバー側ではチェーンの最初にあるシンクです。トランスポート シンクは、シリアル化したメッセージを転送するだけでなく、サーバーにヘッダーを送信したり、サーバーから呼び出しが返されたときにヘッダーやストリームを取得したりします。これらのシンクはチャネルに組み込まれており、拡張できません。

既定のフォーマッタの交換

チャネルは抽象的なネットワーク機構であるため、.NET リモート処理システムを構成して、システムに実装されたチャネルと、選択した任意のフォーマッタを結合できます。これを行うには、チャネル プロパティの IDictionary 実装、サーバー側のフォーマッタ、およびクライアント側のフォーマッタを受け取るチャネル コンストラクターを使用します。フォーマッタは構成ファイルで指定することもできます。次の例では、.NET リモート処理構成システムに対して、HttpChannel の作成を指定し、クライアント側で BinaryClientFormatterSink を使用するように指定しています。

<configuration>
   <system.runtime.remoting>
      <application>
         <channels>
            <channel ref="http">
               <clientProviders>
                  <formatter ref="binary"/>
               </clientProviders>
         <channels>
      </application>
   </system.runtime.remoting>
</configuration> 

上のコードと同じ処理をプログラムで実行するコードを次に示します。このコードでは、GetServerString および GetServerTime を実装するリモート インターフェイス型の IService が存在することを想定しています。

Imports System
Imports System.Collections
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Http

Public Class ClientProcess
  <MTAThread()> _
  Public Shared Sub Main()
      
    ' Note that any name/value pairs of configuration attributes can be 
    ' placed in this dictionary (the configuration system calls this same 
    ' constructor).
    Dim properties As New Hashtable()
    properties("name") = "HttpBinary"
     
    ChannelServices.RegisterChannel(New HttpChannel(properties, New BinaryClientFormatterSinkProvider(), Nothing))
    ' The last parameter above (Nothing) is the server sink provider chain 
    ' to obtain the default behavior (which includes SOAP and 
    ' binary formatters on the server side).
    Dim service As IService = CType(Activator.GetObject(GetType(IService), "http://computer:8080/SAService"), IService)
      
    Console.WriteLine("Server string is: " + service.GetServerString())
    Console.WriteLine("Server time is: " + service.GetServerTime())
  End Sub
   
End Class 
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;

public class ClientProcess{

  public static void Main(string[] Args){
        
    // Note that any name/value pairs of configuration attributes can be 
    // placed in this dictionary (the configuration system calls this 
    // same HttpChannel constructor).
    IDictionary properties = new Hashtable();
    properties["name"] = "HttpBinary";

    // The last parameter below is the server sink provider chain 
    // to obtain the default behavior (which includes SOAP and binary 
    // formatters) on the server side.
    ChannelServices.RegisterChannel(new HttpChannel(properties, new BinaryClientFormatterSinkProvider(), null));

    IService service = (IService)Activator.GetObject(typeof(IService),"http://computer:8080/SAService");
        
    Console.WriteLine("Server string is: " + service.GetServerString());
    Console.WriteLine("Server time is: " + service.GetServerTime());      
  }
}

インターネット インフォメーション サービス (IIS : Internet Information Services) でホストされるこのチャネルとフォーマッタの組み合わせの完全な例については、「リモート処理の例 : インターネット インフォメーション サービス (IIS: Internet Information Services) でのホスティング」を参照してください。

上の例のクライアントが、SoapClientFormatterSinkfrlrfSystemRuntimeRemotingChannelsSoapClientFormatterSinkClassTopic オブジェクトで TcpChannel オブジェクトを使用するように変更するには、次のコードに示すように、名前空間と RegisterChannel の呼び出しのみを変更する必要があります。

ChannelServices.RegisterChannel(New TcpChannel(properties, New SoapClientFormatterSinkProvider(), Nothing))
ChannelServices.RegisterChannel(new TcpChannel(properties, new SoapClientFormatterSinkProvider(), null));

参照

概念

インターネット インフォメーション サービス (IIS) でのリモート オブジェクトのホスト
リモート処理の例 : インターネット インフォメーション サービス (IIS: Internet Information Services) でのホスティング

その他のリソース

高度なリモート処理