Freigeben über


Senken und Senkenketten

Dieses Thema bezieht sich auf eine veraltete Technologie, die zum Zwecke der Abwärtskompatibilität mit vorhandenen Anwendungen beibehalten wird und nicht für die neue Entwicklung empfohlen wird. Verteilte Anwendungen sollten jetzt mit Windows Communication Foundation (WCF) entwickelt werden.

Clients machen Methodenaufrufe für Remoteobjekte, indem sie Nachrichten an die Remoteanwendungsdomäne senden. Dies erfolgt durch eine Gruppe von Channelobjekten. Die Clientanwendungsdomäne enthält einen Clientchannel, und die Remoteanwendungsdomäne enthält einen Remotechannel. Jeder Channel besteht aus einer Reihe von Channelsenken, die in einer Kette miteinander verknüpft sind. Die folgende Abbildung zeigt die Struktur einer Basis-Channelsenkenkette.

Senken und Senkenketten

Vor dem Senden oder nach dem Empfang einer Nachricht senden Channels jede Nachricht durch eine Kette von Channelsenkenobjekten. Diese Senkenkette enthält Senken, die für die Grundfunktionen des Channels erforderlich sind, wie z. B. Formatierungsprogramm-, Transport- oder Stapelgeneratorsenken. Sie können die Channelsenkenkette jedoch anpassen, um mit einer Nachricht oder einem Stream besondere Aufgaben auszuführen. Jede Channelsenke implementiert entweder IClientChannelSink oder IServerChannelSinkfrlrfSystemRuntimeRemotingChannelsIServerChannelSinkClassTopic. Die erste Channelsenke des Clients muss auch IMessageSinkfrlrfSystemRuntimeRemotingMessagingIMessageSinkClassTopic implementieren. Er implementiert in der Regel IClientFormatterSink (erbt von IMessageSink, IChannelSinkBase und IClientChannelSink) und wird als Formatierungssenke bezeichnet, weil er die eingehende Nachricht in einen Stream (ein IMessagefrlrfSystemRuntimeRemotingMessagingIMessageClassTopic-Objekt) umwandelt.

Die Channelsenkenkette verarbeitet alle Nachrichten, die an eine oder von einer Anwendungsdomäne gesendet werden. Eine Channelsenke hat Zugriff auf die Nachricht, die verarbeitet wird. Bei der nachfolgenden Verarbeitung wird die Nachricht verwendet, die nach der Verarbeitung an das System zurückgegeben wurde. Dies ist eine natürliche Stelle, um einen Protokollierungsdienst oder irgendeine Art von Filter zu implementieren.

Jede Channelsenke verarbeitet den Stream und übergibt ihn anschließend an die nächste Channelsenke. Das bedeutet, dass die Senken vor oder nach einer bestimmten Senke wissen müssen, was mit dem an sie übergebenen Stream zu tun ist.

tdzwhfy3.note(de-de,VS.100).gifHinweis:
Nachrichtensenken dürfen keine Ausnahmen auslösen. Eine Methode, mit der eine Nachrichtensenke dies steuern kann, besteht darin, den Methodencode in try-catch-Blöcke einzubinden.

Channelsenkenanbieter (Objekte, die die Schnittstelle IClientChannelSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientChannelSinkProviderClassTopic, IClientFormatterSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientFormatterSinkProviderClassTopic oder IServerChannelSinkProvider implementieren) sind für die Erstellung der Channelsenken zuständig, die .NET-Remotenachrichten verarbeiten. Beim Aktivieren eines Remotetyps wird die Channelsenke aus dem Channel abgerufen, und die CreateSink-Methode wird für den Senkenanbieter aufgerufen, um die erste Channelsenke aus der Kette abzurufen.

Die Nachrichtenübertragung zwischen Client und Server erfolgt über Channelsenken. Channelsenken werden auch in einer Kette miteinander verknüpft. Wenn die CreateSink-Methode für einen Senkenanbieter aufgerufen wird, sollte sie Folgendes ausführen:

  • Eine Channelsenke erstellen.

  • CreateSink für den nächsten Senkenanbieter in der Kette aufrufen.

  • Sicherstellen, dass die nächste Senke und die aktuelle Senke miteinander verknüpft sind.

  • Die Senke an den Aufrufer zurückgeben.

Channelsenken sind dafür zuständig, alle an sie gerichteten Aufrufe an die nächste Senke in der Kette weiterzuleiten. Außerdem müssen sie einen Mechanismus zum Speichern eines Verweises auf die nächste Senke bereitstellen.

Channelsenken sind bei dem, was sie entlang der Senkenkette senden, sehr flexibel. So können z. B. Sicherheitssenken, die die Authentifizierung vor dem Senden der eigentlichen serialisierten, ursprünglichen Nachricht aushandeln, die ganze Channelnachricht nehmen, den Inhalt des Streams durch ihren eigenen Inhalt ersetzen und ihn entlang der Senkenkette zur Remoteanwendungsdomäne senden. Bei der Rückübertragung kann die Sicherheitssenkedie Antwortnachricht abfangen und damit eine Konversation mit den entsprechenden Sicherheitssenken in der Remoteanwendungsdomäne beginnen. Nachdem eine Vereinbarung getroffen wurde, kann die ursprüngliche Sicherheitssenke den ursprünglichen Inhaltsdatenstrom an die Remoteanwendungsdomäne senden.

Nachrichtenverarbeitung in der Channelsenkenkette

Nachdem das .NET-Remotesystem einen Channel gefunden hat, der die Nachricht verarbeiten kann, übergibt der Channel die Nachricht an den Formatierungssenke, indem er

SyncProcessMessage (oder AsyncProcessMessage) aufruft. Die Formatierungssenke erstellt das Transportheaderarray und ruft GetRequestStream für die nächste Senke auf. Dieser Aufruf wird entlang der Senkenkette weitergeleitet, und jede Senke kann einen Anforderungsstream erstellen, der wieder an die Formatierungssenken übergeben wird. Wenn GetRequestStream einen null-Verweis (Nothing in Visual Basic) zurückgibt, erstellt die Formatierungssenke eine eigene Senke, die für die Serialisierung verwendet werden soll. Nachdem die Rückgabe für diesen Aufruf erfolgt ist, wird die Nachricht serialisiert. Anschließend wird für die erste Channelsenke in der Senkenkette die entsprechende Verarbeitungsmethode für die Nachricht aufgerufen.

Senken können keine Daten in den Stream schreiben, können aber Daten aus dem Stream lesen oder bei Bedarf einen neuen Stream weiterleiten. Senken können dem Headerarray auch Header hinzufügen (wenn sie nicht zuvor GetRequestStream für die nächste Senke aufgerufen haben) und sich selbst dem Senkenstapel hinzufügen, bevor sie den Aufruf an die nächste Senke weiterleiten. (Der Synchronisierungsstapel wird verwendet, damit asynchrone Aufrufe nach deren Abschluss einen Rückruf an den Aufrufer ausführen können.) Wenn der Aufruf die Transportsenke am Ende der Kette erreicht, sendet die Transportsenke die Header und die serialisierte Nachricht über den Channel an den Server, wo der gesamte Prozess umgekehrt wird. Die Transportsenke (auf dem Server) ruft die Header und die serialisierte Nachricht von der Serverseite des Streams ab und leitet diese durch die Senkenkette bis zur Formatierungssenke weiter. Die Formatierungssenke deserialisiert die Nachricht und leitet sie an das .NET-Remotesystem weiter, wo die Nachricht wieder in einen Methodenaufruf umgewandelt und am Serverobjekt aufgerufen wird.

Erstellen von Channelsenkenketten

Zum Erstellen einer neuen Channelsenke müssen Sie das .NET-Remotesystem so implementieren und konfigurieren, dass es eine IServerChannelSinkProvider-Implementierung oder eine IClientChannelSinkProvider-Implementierung erkennt, die die benutzerdefinierte IClientChannelSink-Implementierung oder die IServerChannelSink-Implementierung erstellen oder die nächste Senke in der Kette abrufen kann. Sie können die abstrakte BaseChannelSinkWithProperties-Klasse verwenden, um die benutzerdefinierten Channelsenken zu implementieren.

Erstellen eines Channelsenkenanbieters

Beim Erstellen eines Channels können Anwendungen Server- oder Client-Channelsenkenanbieter als Parameter bereitstellen. Channelsenkenanbieter müssen in einer Kette gespeichert werden, und der Entwickler muss alle Channelsenkenanbieter verketten, bevor der Äußerste an den Channelkonstruktor übergeben wird. Der Channelsenkenanbieter implementiert für diesen Zweck eine Next-Eigenschaft. Das folgende Codebeispiel veranschaulicht die Erstellung eines Client-Channelsenkenanbieters. Ein vollständiges Beispiel finden Sie unter Remotingbeispiel: Channelsenkenanbieter.

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(de-de,VS.100).gifHinweis:
Wenn in einer Konfigurationsdatei mehrere Channelsenkenanbieter angegeben sind, werden diese vom .NET-Remotesysteme in der Reihenfolge verkettet, in der sie in der Konfigurationsdatei gefunden werden. Die Channelsenkenanbieter werden erstellt, wenn der Channel während des Aufrufs von Configure erstellt wird.

Formatierungssenken

Formatierungssenken serialisieren die Channelnachricht als Objekt, das IMessage implementiert, in den Nachrichtenstream. Manche Implementierungen von Formatierungssenke verwenden die vom System bereitgestellten Formatierungstypen (BinaryFormatterfrlrfSystemRuntimeSerializationFormattersBinaryBinaryFormatterClassTopic und SoapFormatterfrlrfSystemRuntimeSerializationFormattersSoapSoapFormatterClassTopic). Andere Implementierungen verfügen über eigene Möglichkeiten, um die Channelnachricht in den Stream zu transformieren.

Die Funktion der Formatierungssenke besteht darin, die erforderlichen Header zu erstellen und die Nachricht in den Stream zu serialisieren. Nach Erreichen der Formatierungssenke wird die Nachricht über den SyncProcessMessage-Aufruf oder den AsyncProcessMessage-Aufruf an alle Senken in der Channelsenkenkette weitergeleitet. In dieser Phase wurde die Nachricht bereits serialisiert und kann nicht geändert werden.

tdzwhfy3.note(de-de,VS.100).gifHinweis:
Senken, die die Nachricht selbst erstellen oder ändern müssen, müssen in der Senkenkette vor dem Formatierungsprogramm platziert werden. Dies wird ganz einfach durch eine Implementierung von IClientFormatterSink erreicht. Dadurch wird dem System mitgeteilt, dass es einen Verweis auf die Formatierungssenke besitzt. Die eigentliche Formatierungssenke kann dann weiter hinten in der Senkenkette platziert werden.

Bei der Rückübertragung transformiert die Formatierungssenke den Nachrichtenstream wieder in das Objekt der Channelnachricht (Rückgabenachricht). Die erste Senke des Clients muss die IClientFormatterSink-Schnittstelle implementieren. Wenn CreateSink an den Channel zurückgegeben wird, wird der zurückgegebene Verweis in einen IClientFormatterSink-Typ umgewandelt, sodass die SyncProcessMessage-Methode aufgerufen werden kann. Beachten Sie, dass IClientFormatterSink von IMessageSink abgeleitet ist. Wenn die Umwandlung fehlschlägt, löst das System eine Ausnahme aus.

Benutzerdefinierte Channelsenken

Auf dem Client werden benutzerdefinierte Channelsenken zwischen der Formatierungssenke und der letzten Transportsenke in die Objektkette eingefügt. Wenn Sie eine benutzerdefinierte Channelsenke in den Client- oder Serverchannel einfügen, können Sie IMessage an einer der folgenden Stellen verarbeiten:

  • Während des Prozesses, bei dem ein als Nachricht dargestellter Aufruf in einen Stream konvertiert und über die Verbindung übertragen wird.

  • Während des Prozesses, bei dem ein Stream aus der Verbindung genommen und an die letzte Nachrichtensenke vor dem Remoteobjekt auf dem Server oder dem Proxyobjekt (auf dem Client) gesendet wird.

Abhängig davon, ob es sich um einen ausgehenden oder einen eingehenden Aufruf handelt, können benutzerdefinierte Senken Daten aus dem Stream lesen oder in den Stream schreiben und den Headern nach Bedarf zusätzliche Information hinzufügen. In dieser Phase wurde die Nachricht bereits vom Formatierungsprogramm serialisiert und kann nicht geändert werden. Wenn der Nachrichtenaufruf an die Transportsenke am Ende der Kette weitergeleitet wird, schreibt die Transportsenke die Header in den Stream und leitet den Stream mit dem vom Channel vorgegebenen Transportprotokoll an die Transportsenke auf dem Server weiter.

Transportsenken

Die Transportsenke ist auf dem Client die letzte Senke in der Kette und auf dem Server die erste Senke in der Kette. Die Transportsenke überträgt nicht nur die serialisierte Nachricht, sondern sie ist darüber hinaus für das Senden der Header an den Server sowie das Abrufen der Header und des Streams zuständig, wenn ein Aufruf vom Server zurückgegeben wird. Diese Senken sind in den Channel integriert und können nicht erweitert werden.

Ersetzen des Standardformatierungsprogramms

Da es sich bei einem Channel um einen abstrakten Netzwerkmechanismus handelt, können Sie das .NET-Remotesystem so konfigurieren, dass ein vom System implementierter Channel mit einem Formatierungsprogramm Ihrer Wahl kombiniert werden kann. Verwenden Sie dazu den Channelkonstruktor, der eine IDictionary-Implementierung der Channeleigenschaften, ein Formatierungsprogramm auf dem Server und ein Formatierungsprogramm auf dem Client annimmt. Sie können das Formatierungsprogramm auch in einer Konfigurationsdatei angeben. Im folgenden Beispiel wird das .NET-Remotekonfigurationssystem angewiesen, BinaryClientFormatterSink zu erstellen, auf dem Client aber HttpChannel zu verwenden.

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

Der folgende Code macht das Gleiche programmgesteuert, setzt aber den Remoteschnittstellentyp IService voraus, der GetServerString und GetServerTime implementiert:

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());      
  }
}

Ein vollständiges Beispiel für diese Kombination aus Channel und Formatierungsprogramm, die in Internetinformationsdiensten (Internet Information Services, IIS) gehostet wird, finden Sie unter Remotingbeispiel: Hosting in Internetinformationsdiensten (IIS).

Wenn dieser Client ein TcpChannel-Objekt mit dem SoapClientFormatterSinkfrlrfSystemRuntimeRemotingChannelsSoapClientFormatterSinkClassTopic-Objekt verwenden soll, müssen Sie nur die Namespaces und den RegisterChannel **** -Aufruf wie im folgenden Codebeispiel gezeigt ändern:

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

Siehe auch

Konzepte

Hosten von Remoteobjekten in Internetinformationsdiensten (IIS)
Remotingbeispiel: Hosting in Internetinformationsdiensten (IIS)

Weitere Ressourcen

Remoting für Fortgeschrittene