Récepteurs et chaînes de récepteurs
Cette rubrique est spécifique à la technologie héritée assurant la compatibilité descendante avec des applications existantes et n'est pas recommandée en cas de nouveau développement. Les applications distribuées doivent maintenant être développées à l'aide de Windows Communication Foundation (WCF).
Les clients effectuent des appels de méthode sur des objets distants en envoyant des messages au domaine d'application distant. Pour ce faire, on utilise un jeu d'objets de canal. Le domaine d'application client contient un canal client et le domaine d'application distant contient un canal distant. Chaque canal est composé d'une série de récepteurs de canal liés dans une chaîne. L'illustration suivante montre la structure d'une chaîne du récepteur de canal de base.
Les canaux envoient chaque message sur une chaîne d'objets de récepteur de canal avant d'envoyer un message et après sa réception. Cette chaîne du récepteur contient les récepteurs requis pour les fonctionnalités de canal de base, par exemple des récepteurs de formateur, de transport ou de pile, mais vous pouvez la personnaliser afin d'effectuer des tâches spéciales dans un message ou un flux. Chaque récepteur de canal implémente IClientChannelSink ou IServerChannelSinkfrlrfSystemRuntimeRemotingChannelsIServerChannelSinkClassTopic. Le premier récepteur de canal du client doit également implémenter IMessageSinkfrlrfSystemRuntimeRemotingMessagingIMessageSinkClassTopic. Il implémente généralement IClientFormatterSink (lequel hérite de IMessageSink, IChannelSinkBaseet IClientChannelSink) et est appelé récepteur de formateur, car il transforme le message entrant en un flux (un objet IMessagefrlrfSystemRuntimeRemotingMessagingIMessageClassTopic.
La chaîne du récepteur de canal traite tout message envoyé à ou à partir d'un domaine d'application. Un récepteur de canal a accès au message en cours de traitement et le traitement suivant utilise le message retourné au système après traitement. C'est l'emplacement logique pour implémenter un service d'enregistrement ou tout type de filtre.
Chaque récepteur de canal traite le flux, puis le passe au récepteur de canal suivant, ce qui signifie que les récepteurs situés avant ou après un récepteur spécifique savent gérer le flux de données qui leur est passé.
Remarque : |
---|
Les récepteurs de messages ne doivent pas lever d'exceptions. Pour ce faire, vous pouvez par exemple encapsuler le code de méthode dans des blocs try-catch. |
Les fournisseurs de récepteur de canal (objets qui implémentent l'interface IClientChannelSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientChannelSinkProviderClassTopic, IClientFormatterSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientFormatterSinkProviderClassTopic ou IServerChannelSinkProvider) sont chargés de créer les récepteurs de canal qui traitent les messages .NET Remoting. Lorsqu'un type distant est activé, le fournisseur de récepteur de canal est récupéré à partir du canal et la méthode CreateSink est appelée sur le fournisseur de récepteur pour récupérer le premier récepteur de canal de la chaîne.
Ces récepteurs de canal transportent les messages entre le client et le serveur. Les récepteurs de canal sont également liés dans une chaîne. Lorsque la méthode CreateSink est appelée sur un fournisseur de récepteur, il doit effectuer les opérations suivantes :
Créer un récepteur de canal.
Appeler CreateSink sur le prochain fournisseur de récepteur de la chaîne.
S'assurer que le récepteur suivant est lié à l'actuel.
Retourner son récepteur à l'appelant.
Les récepteurs de canal doivent transférer tous les appels qu'ils reçoivent au récepteur suivant de la chaîne et lui fournir un mécanisme de stockage d'une référence.
Les récepteurs de canal bénéficient d'une grande souplesse dans ce qu'ils envoient à la chaîne de récepteurs. Par exemple, les récepteurs de sécurité qui négocient l'authentification avant d'envoyer le véritable message d'origine sérialisé peuvent conserver l'ensemble du message de canal, remplacer le flux de contenu par leur propre contenu et l'envoyer à la chaîne de récepteurs et au domaine d'application distant. Lors du retour, le récepteur de sécurité peut intercepter le message de réponse en créant une conversation avec les récepteurs de sécurité correspondants du domaine d'application distant. Une fois qu'un accord est atteint, le récepteur de sécurité de l'émetteur peut envoyer le flux de contenu d'origine au domaine d'application distant.
Traitement des messages dans la chaîne du récepteur de canal
Une fois que le système .NET Remoting localise un canal qui peut traiter le message, le canal passe le message au récepteur du canal de formateur en appelant
SyncProcessMessage (ou AsyncProcessMessage). Le récepteur de formateur crée ensuite le tableau d'en-têtes de transport et appelle GetRequestStream sur le récepteur suivant. Cet appel est renvoyé dans la chaîne de récepteurs; n'importe quel récepteur peut créer un flux de demande qui est alors repassé au récepteur de formateur. Si GetRequestStream retourne une référence Null (Nothing en Visual Basic), le récepteur de formateur crée son propre récepteur à utiliser pour la sérialisation. Après le retour de cet appel, le message est sérialisé et la méthode de traitement de message appropriée est appelée sur le premier récepteur de canal de la chaîne.
Les récepteurs ne peuvent pas écrire de données dans le flux, mais ils peuvent le lire ou passer un nouveau flux lorsque cela est nécessaire. Les récepteurs peuvent également ajouter des en-têtes au tableau d'en-têtes (s'ils n'ont pas encore appelé GetRequestStream sur le récepteur suivant) et s'ajouter à la pile du récepteur avant de transférer l'appel au récepteur suivant. (La pile de synchronisation permet d'autoriser les appels asynchrones à rappeler l'appelant lorsqu'ils sont terminés.) Lorsque l'appel atteint le récepteur de transport à l'extrémité de la chaîne, le récepteur de transport envoie les en-têtes et le message sérialisé sur le canal au serveur où l'ensemble du processus est alors inversé. Le récepteur de transport (du serveur) récupère les en-têtes et le message sérialisé du coté serveur du flux de données et transfère ces éléments dans la chaîne de récepteurs jusqu'au récepteur de formateur. Le récepteur de formateur désérialise ensuite le message et le transfère au système .NET Remoting où le message est converti en un appel de méthode et est appelé sur l'objet serveur.
Création de chaînes du récepteur de canal
Pour créer un récepteur de canal, vous devez implémenter le système .NET Remoting et le configurer pour qu'il reconnaisse une implémentation IServerChannelSinkProvider ou IClientChannelSinkProvider, qui peut créer votre implémentation personnalisée IClientChannelSink ou IServerChannelSink, ou récupérer le récepteur suivant de la chaîne. Vous pouvez utiliser la classe abstraite BaseChannelSinkWithProperties pour vous aider à implémenter vos récepteurs de canal personnalisés.
Génération d'un fournisseur de récepteur de canal
Les applications peuvent fournir des fournisseurs de récepteur de canal client ou serveur en tant que paramètres lors de la construction d'un canal. Les fournisseurs de récepteur de canal doivent être stockés dans une chaîne et il incombe au développeur de lier tous les fournisseurs de récepteur de canal avant de passer le fournisseur externe au constructeur de canal. À cet effet, le fournisseur de récepteur de canal implémente une propriété Next. L'exemple de code suivant illustre comment générer un fournisseur de récepteur de canal client. Un exemple complet est disponible sur Exemple de communication à distance : fournisseur de récepteur de canal.
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;
}
Remarque : |
---|
Lorsque plusieurs fournisseurs de récepteur de canal sont fournis dans un fichier de configuration, le système .NET Remoting les chaîne dans l'ordre dans lequel ils apparaissent dans le fichier de configuration. Les fournisseurs de récepteur de canal sont créés lors de la création du canal, pendant l'appel de Configure. |
Récepteurs de formateur
Les récepteurs de formateur sérialisent le message de canal dans un flux de messages en tant qu'objet qui implémente IMessage. Certaines implémentations de récepteur de formateur utilisent les types de formateurs fournis par le système (BinaryFormatterfrlrfSystemRuntimeSerializationFormattersBinaryBinaryFormatterClassTopic et SoapFormatterfrlrfSystemRuntimeSerializationFormattersSoapSoapFormatterClassTopic). Les autres implémentations peuvent transformer le message de canal en flux par leurs propres moyens.
La fonction du récepteur de formateur consiste à générer les en-têtes nécessaires et à sérialiser le message dans le flux. Après avoir été traité par le récepteur de formateur, le message est transféré à tous les récepteurs de la chaîne via des appels à SyncProcessMessage ou AsyncProcessMessage. À ce stade, le message a déjà été sérialisé et ne peut pas être modifié.
Remarque : |
---|
Les récepteurs qui doivent créer ou modifier le message doivent être placés dans la chaîne de récepteurs avant le formateur. Cela peut être mis en place facilement, en implémentant IClientFormatterSink, indiquant ainsi au système qu'il a une référence au récepteur de formateur. Le récepteur de formateur réel peut alors être placé ultérieurement dans la chaîne de récepteurs. |
Lors du retour, le récepteur de formateur reconvertit le flux de message en objet de message de canal (message de retour). Le premier récepteur de client doit implémenter l'interface IClientFormatterSink. Lorsque CreateSink revient au canal, une conversion du type de la référence retournée est effectué vers un type IClientFormatterSink de façon à pouvoir appeler la méthode SyncProcessMessage. N'oubliez pas que IClientFormatterSink est dérivé de IMessageSink. Si le transtypage échoue, le système lève une exception.
Récepteurs de canal personnalisés
Sur le client, les récepteurs de canal personnalisés sont insérés dans la chaîne d'objets entre le récepteur de formateur et le dernier récepteur de transport. L'insertion d'un récepteur de canal personnalisé dans le canal client ou serveur vous permet de traiter le IMessage à l'un des moments suivants :
Pendant le processus par lequel un appel représenté sous forme de message est converti en flux et transmis.
Pendant le processus par lequel un flux quitte la transmission et est envoyé au dernier récepteur de messages avant l'objet distant sur le serveur ou l'objet proxy (sur le client).
Les récepteurs personnalisés peuvent lire ou écrire des données (selon que l'appel est entrant ou sortant) dans le flux et ajouter des informations supplémentaires dans les en-têtes. À ce stade, le message a déjà été sérialisé par le formateur et ne peut pas être modifié. Lorsque l'appel de message est transféré au récepteur de transport à la fin de la chaîne, le récepteur de transport écrit les en-têtes dans le flux de données et le transfère au récepteur de transport du serveur à l'aide du protocole de transport dicté par le canal.
Récepteurs de transport
Le récepteur de transport est le dernier récepteur dans la chaîne du client et le premier récepteur dans la chaîne du serveur. En plus de transporter le message sérialisé, le récepteur de transport est également chargé d'envoyer les en-têtes au serveur et de récupérer les en-têtes et le flux lorsque l'appel revient du serveur. Ces récepteurs sont construits dans le canal et ne peuvent pas être étendus.
Remplacement du formateur par défaut
Comme un canal est un mécanisme de mise en réseau abstrait, vous pouvez configurer le système .NET Remoting de façon à combiner un canal implémenté par système avec le formateur de votre choix. Pour ce faire, utilisez le constructeur de canal qui accepte une implémentation IDictionary des propriétés de canal, un formateur sur le serveur et un formateur sur le client. Vous pouvez également spécifier le formateur dans un fichier de configuration. L'exemple suivant demande au système de configuration .NET Remoting de créer un HttpChannel mais d'utiliser le BinaryClientFormatterSink sur le client.
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="http">
<clientProviders>
<formatter ref="binary"/>
</clientProviders>
<channels>
</application>
</system.runtime.remoting>
</configuration>
Le code suivant procède de même via un programme, en supposant que l'interface distante est de type IService
et implémente GetServerString
ainsi que GetServerTime
:
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());
}
}
Pour un exemple complet de cette combinaison de canal et de formateur hébergée dans les services Internet (IIS), consultez Exemple de communication à distance : hébergement dans les services Internet (IIS).
Pour modifier ce client de façon à utiliser un objet TcpChannel avec l'objet SoapClientFormatterSinkfrlrfSystemRuntimeRemotingChannelsSoapClientFormatterSinkClassTopic, vous ne devez modifier que les espaces de noms et l'appel à RegisterChannel **** , comme illustré dans le code suivant :
ChannelServices.RegisterChannel(New TcpChannel(properties, New SoapClientFormatterSinkProvider(), Nothing))
ChannelServices.RegisterChannel(new TcpChannel(properties, new SoapClientFormatterSinkProvider(), null));
Voir aussi
Concepts
Hébergement d'objets distants dans les Services Internet (IIS)
Exemple de communication à distance : hébergement dans les Services Internet (IIS)