Receptores y cadenas de receptores

Este tema es específico de una tecnología heredada que se mantiene para la compatibilidad con versiones anteriores con aplicaciones existentes y no se recomienda para nuevo desarrollo. Las aplicaciones distribuidas se deberían desarrollar utilizando Windows Communication Foundation (WCF).

Los clientes realizan las llamadas de método en objetos remotos enviando los mensajes al dominio de aplicación remota. Un conjunto de objetos de canal logra esto. El dominio de aplicación de cliente contiene un canal de cliente y el dominio de aplicación remota contiene un canal remoto. Cada canal está compuesto por una serie de receptores de canal que se vinculan en una cadena. La siguiente ilustración muestra la estructura de una cadena de receptores de canal básica.

Receptores y cadenas de receptores

Los canales envían cada uno de los mensajes por una cadena de objetos de receptores de canales antes de enviar un mensaje o después de recibirlo. Esta cadena de receptores contiene los receptores necesarios para la funcionalidad básica del canal, como son los receptores de formateador, de transportador o de generador de pila, pero la cadena de receptores de canales se puede personalizar para que realice tareas especiales con un mensaje o una secuencia. Cada receptor de canal implementa IClientChannelSink o IServerChannelSinkfrlrfSystemRuntimeRemotingChannelsIServerChannelSinkClassTopic. El primer receptor de canal en el cliente también debe implementar IMessageSinkfrlrfSystemRuntimeRemotingMessagingIMessageSinkClassTopic. Normalmente implementa IClientFormatterSink (que hereda de IMessageSink, IChannelSinkBasey de IClientChannelSink) y se denomina un receptor de formateador porque transforma el mensaje entrante en una secuencia (un objeto IMessagefrlrfSystemRuntimeRemotingMessagingIMessageClassTopic).

La cadena de receptores de canal procesa cualquier mensaje que se envía a un dominio de aplicación o desde un dominio de aplicación. Un receptor de canal tiene acceso al mensaje que se está procesando y el proceso siguiente utiliza el mensaje que se devuelve al sistema después de haber sido procesado. Éste es un lugar lógico para implementar un servicio de registro o cualquier otra clase filtro.

Cada receptor de canal procesa la secuencia y, a continuación, pasa la secuencia al receptor de canal siguiente, lo que significa que los receptores situados antes o después de un receptor concreto deberían saber qué hacer con la secuencia que se les ha pasado.

tdzwhfy3.note(es-es,VS.100).gifNota:
Los receptores del mensaje no deben producir excepciones. Una de las formas de que un receptor de mensajes pueda controlar esto es ajustando el código de método en bloques try-catch.

Los proveedores de receptores de canal (objetos que implementan el IClientChannelSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientChannelSinkProviderClassTopic, IClientFormatterSinkProviderfrlrfSystemRuntimeRemotingChannelsIClientFormatterSinkProviderClassTopico la interfaz IServerChannelSinkProvider) son responsables de la creación de los receptores de canal que procesan los mensajes de .NET Remoting. Cuando se activa un tipo remoto, el proveedor de receptores de canal se recupera del canal y se llama al método CreateSink en el proveedor de receptores para recuperar el primer receptor de canal de la cadena.

Los receptores de canal son los responsables de transportar los mensajes entre el cliente y el servidor. Asimismo, los receptores de canal están vinculados en una cadena. Cuando se llama al método CreateSink en un proveedor de receptores, debería hacer lo siguiente:

  • Cree un receptor de canal.

  • Llame a CreateSink del siguiente proveedor de receptor en la cadena.

  • Asegúrese de que el siguiente receptor y el actual están vinculados juntos.

  • Devuelva su receptor al llamador.

Los receptores de canal son los responsables de reenviar todas las llamadas realizadas en ellos al siguiente receptor de la cadena y deberían proporcionar un mecanismo para almacenar una referencia en el siguiente receptor.

Los receptores de canal tienen una gran flexibilidad en lo que envían por la cadena de receptores. Por ejemplo, los receptores de seguridad que negocian la autenticación antes de enviar el mensaje original serializado real pueden contener el mensaje del canal completo, reemplazar la secuencia de contenidos con su propio contenido y enviarlo por la cadena de receptores y hasta el dominio de aplicación remota. En el trayecto de vuelta, el receptor de seguridad puede interceptar el mensaje de respuesta, creando una conversación con los receptores de seguridad correspondientes en el dominio de aplicación remota. Una vez llegado a un acuerdo, el receptor de seguridad originario puede enviar la secuencia de contenidos original al dominio de aplicación remota.

Procesamiento de mensajes en la cadena de receptores de canal

Cuando el sistema .NET Remoting encuentra un canal que puede procesar el mensaje, el canal pasa el mensaje al receptor de canal del formateador llamando

SyncProcessMessage (o AsyncProcessMessage). El receptor del formateador crea la matriz del encabezado de transporte y llama a GetRequestStream del siguiente receptor del formateador. Esta llamada se envía por la cadena de receptores y cualquier receptor puede crear una secuencia de solicitud que se devolverá al receptor del formateador. Si GetRequestStream devuelve una referencia null (Nothing en Visual Basic), el receptor de formateador crea su propio receptor para utilizarlo en la serialización. Una vez que ha llegado esta llamada, se serializa el mensaje y se llama al método de procesamiento de mensajes apropiado de la primera cadena del receptor de la cadena de receptores.

Los receptores no pueden escribir los datos en la secuencia, pero pueden leerla o pasar una nueva por donde sea necesario. Los receptores también pueden agregar encabezados a la matriz del encabezado (si previamente no han llamado a GetRequestStream en el siguiente receptor) y agregarse a la pila del receptor antes de enviar la llamada al siguiente receptor. (La pila de sincronización se utiliza para permitir a las llamadas asincrónicas volver a llamar al llamador cuando se completan.) Cuando la llamada llega al último receptor de transporte de la cadena, el receptor de transporte envía al servidor los encabezados y el mensaje serializado a través del canal, donde se invierte el proceso completo. El receptor de transporte (del servidor) invierte los encabezados y el mensaje serializado de la secuencia del servidor y los envía por la cadena de receptores hasta que se alcanza el receptor de formateador. A continuación, el receptor de formateadores deserializa el mensaje y lo envía al sistema de .NET Remoting, donde el mensaje se convierte en una llamada de método y se invoca en el objeto del servidor.

Crear las cadenas de receptores de canal

Para crear un nuevo receptor de canal, debe implementar y configurar el sistema .NET Remoting para reconocer una implementación IServerChannelSinkProvider o IClientChannelSinkProvider, que puede crear su implementación personalizada IClientChannelSink o IServerChannelSink o recuperar el siguiente receptor de la cadena. Puede utilizar la clase abstracta BaseChannelSinkWithProperties para ayudar a implementar sus receptores de canal personalizados.

Generar un proveedor de receptores de canal

Al construir un canal, las aplicaciones pueden proporcionar proveedores de receptores del canal de servidor o de cliente como parámetros. Los proveedores de receptores de canal deberían estar almacenados en una cadena y el programador es el responsable de encadenar todos los proveedores de receptores de canal antes de pasar el exterior al constructor del canal. El proveedor de receptores de canal implementa una propiedad Next para este propósito. El siguiente ejemplo de código muestra cómo generar un proveedor de receptores del canal de cliente. Puede encontrar un ejemplo completo en Ejemplos de interacción remota: Proveedor de receptores 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;
} 
tdzwhfy3.note(es-es,VS.100).gifNota:
Cuando se suministren varios proveedores de receptores de canal en un archivo de configuración, el sistema .NET Remoting los encadena en el orden en que se encuentran en el archivo de configuración. Los proveedores de receptores de canal se crean al crear el canal durante la llamada a Configure.

Receptores de formateador

Los receptores de formateador serializan el mensaje del canal en la secuencia de mensajes como un objeto que implementa IMessage. Algunas implementaciones del receptor de formateador utilizan los tipos de formateador proporcionados por el sistema (BinaryFormatterfrlrfSystemRuntimeSerializationFormattersBinaryBinaryFormatterClassTopic y SoapFormatterfrlrfSystemRuntimeSerializationFormattersSoapSoapFormatterClassTopic). Otras implementaciones pueden utilizar sus propios medios para transformar el mensaje de canal en la secuencia.

La función del receptor de formateador es generar los encabezados necesarios y serializar el mensaje en la secuencia. Después del receptor de formateador, el mensaje se reenvía a todos los receptores de la cadena de receptores de canal mediante llamadas a SyncProcessMessage o a AsyncProcessMessage. En esta fase, el mensaje ya se ha serializado y no se puede modificar.

tdzwhfy3.note(es-es,VS.100).gifNota:
Los receptores que deben crear o modificar el mensaje deben situarse antes del formateador en la cadena de receptores. Esto se logra con facilidad implementando IClientFormatterSink, indicando, de este modo, al sistema que tiene una referencia al receptor de formateador. El receptor de formateador auténtico se puede situar en la cadena de receptores más adelante.

En el trayecto de vuelta, el receptor de formateador transforma la secuencia de mensajes en el objeto del mensaje de canal (mensaje devuelto). El primer receptor en el cliente debe implementar la interfaz IClientFormatterSink. Cuando CreateSink vuelve al canal, la referencia devuelta se convierte en un tipo IClientFormatterSink para que se pueda llamar al método SyncProcessMessage . Recuerde que IClientFormatterSink deriva de IMessageSink. En caso de error en la devolución, el sistema produce una excepción.

Receptores de canal personalizados

En el cliente, los receptores de canal personalizados se insertan en la cadena de objetos entre el receptor de formateador y el último receptor de transporte. Insertar un receptor de canal personalizado en el cliente o en el canal de servidor le permite procesar el IMessage en uno de los puntos siguientes:

  • Durante el proceso mediante el cual una llamada representada como un mensaje se convierte en una secuencia y se envía a través de la conexión.

  • Durante el proceso mediante el que se extrae una secuencia de la conexión y se envía al último receptor de mensajes situado antes del objeto remoto en el servidor o el objeto proxy (en el cliente).

Los receptores personalizados pueden leer o escribir datos (dependiendo de si la llamada es entrante o saliente) en la secuencia y agregar información adicional a los encabezados que desee. En esta fase, el formateador ya ha serializado el mensaje y no se puede modificar. Cuando la llamada de mensaje se reenvía al receptor de transporte del final de la cadena, el receptor de transporte escribe los encabezados en la secuencia y reenvía la secuencia al receptor de transporte del servidor utilizando el protocolo de transporte dictado por el canal.

Receptores de transporte

El receptor de transporte es el último receptor de la cadena en el cliente y el primer receptor de la cadena en el servidor. Además de transportar el mensaje serializado, el receptor de transporte también es responsable de enviar los encabezados al servidor y recuperar los encabezados y la secuencia cuando se devuelve la llamada del servidor. Estos receptores están generados en el canal y no se pueden extienden.

Reemplazar el formateador predeterminado

Dado que un canal es un mecanismo de conexión de red abstracto, puede configurar el sistema .NET Remoting para combinar un canal implementado en el sistema con el formateador que elija. Puede hacer esto utilizando el constructor del canal que toma una implementación IDictionary de propiedades de canal, un formateador en el servidor y un formateador en el cliente. También puede especificar el formateador en un archivo de configuración. El ejemplo siguiente indica al sistema de configuración de .NET Remoting que cree un HttpChannel pero que utilice el BinaryClientFormatterSink en el cliente.

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

El siguiente código hace lo mismo mediante programación, suponiendo que un tipo de interfaz remoto IService implemente GetServerString y 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());      
  }
}

Para obtener un ejemplo completo de esta combinación de canal y de formateador hospedados en Internet Information Services (IIS), vea Ejemplo de interacción remota: Alojar en Internet Information Services (IIS).

Para cambiar este cliente y que utilice un objeto TcpChannel con el objeto SoapClientFormatterSinkfrlrfSystemRuntimeRemotingChannelsSoapClientFormatterSinkClassTopic, solamente debe cambiar los espacios de nombres y la llamada RegisterChannel **** , como se muestra en el código siguiente:

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

Vea también

Conceptos

Hospedar objetos remotos en Internet Information Services (IIS)
Ejemplo de comunicación remota: hospedar en Internet Information Services (IIS)

Otros recursos

Comunicación remota avanzada