Compartir a través de


Programación del servicio Channel-Level

En este tema se describe cómo escribir una aplicación de servicio de Windows Communication Foundation (WCF) sin usar el System.ServiceModel.ServiceHost y el modelo de objetos asociado.

recibir mensajes

Para estar listo para recibir y procesar mensajes, se requieren los pasos siguientes:

  1. Cree un enlace.

  2. Crear una escucha del canal.

  3. Abrir la escucha del canal.

  4. Lea la solicitud y envíe una respuesta.

  5. Cierre todos los objetos de canal.

Crear un enlace

El primer paso para escuchar y recibir mensajes es crear un enlace. WCF se envía con varios enlaces que integra o proporciona el sistema y que se pueden usar directamente mediante la creación de instancias de uno de ellos. Además, también puede crear su propio enlace personalizado creando una instancia de una clase CustomBinding, que es lo que hace el código de la lista 1.

El ejemplo de código siguiente crea una instancia de System.ServiceModel.Channels.CustomBinding y agrega System.ServiceModel.Channels.HttpTransportBindingElement a su colección Elements, que es una colección de elementos de enlace que se utilizan para crear la pila del canal. En este ejemplo, dado que la colección de elementos solo tiene el HttpTransportBindingElement, la pila del canal resultante solo tiene el canal de transporte HTTP.

Creación de un ChannelListener

Después de crear un enlace, llamamos a Binding.BuildChannelListener para crear la escucha del canal donde el parámetro de tipo es la forma del canal a crear. En este ejemplo se usa System.ServiceModel.Channels.IReplyChannel porque queremos escuchar mensajes entrantes en un patrón de intercambio de mensajes de solicitud/respuesta.

IReplyChannel se usa para recibir mensajes de solicitud y devolver mensajes de respuesta. La llamada IReplyChannel.ReceiveRequest devuelve un System.ServiceModel.Channels.IRequestChannel, que se puede usar para recibir el mensaje de solicitud y para devolver un mensaje de respuesta.

Al crear el agente de escucha, pasamos la dirección de red en la que escucha, en este caso http://localhost:8080/channelapp. En general, cada canal de transporte admite uno o posiblemente varios esquemas de direcciones, por ejemplo, el transporte HTTP admite esquemas http y https.

También pasamos un parámetro vacío System.ServiceModel.Channels.BindingParameterCollection al crear el escuchador. Un parámetro de vinculación es un mecanismo para pasar parámetros que controlan cómo se debe construir el oyente. En nuestro ejemplo, no se usa ningún parámetro de este tipo, por lo que pasamos una colección vacía.

Escucha de mensajes entrantes

Llamamos a continuación ICommunicationObject.Open en el agente de escucha e iniciamos los canales de aceptación. El comportamiento de IChannelListener<TChannel>.AcceptChannel depende de si el transporte está orientado a la conexión o es sin conexión. En el caso de los transportes orientados a la conexión, AcceptChannel bloquea hasta que se produce una nueva solicitud de conexión en el punto en el que devuelve un nuevo canal que representa esa nueva conexión. Para los transportes sin conexión, como HTTP, AcceptChannel devuelve inmediatamente con el único el canal que el agente de escucha de transporte crea.

En este ejemplo, el oyente devuelve un canal que implementa IReplyChannel. Para recibir mensajes en este canal, llamamos primero a ICommunicationObject.Open para colocarlo en un estado listo para la comunicación. Llamamos a continuación a ReceiveRequest que se bloquea hasta que llega un mensaje.

Leer la solicitud y enviar una respuesta

Cuando ReceiveRequest devuelve un RequestContext, obtenemos el mensaje recibido mediante su propiedad RequestMessage. Escribimos la acción y el contenido del cuerpo del mensaje, que suponemos es una cadena.

Para enviar una respuesta, creamos un nuevo mensaje de respuesta pasando en este caso los datos de texto recibidos en la solicitud. A continuación, llamamos Reply a para enviar el mensaje de respuesta.

Cierre de objetos

Para evitar la pérdida de recursos, es muy importante cerrar los objetos usados en las comunicaciones cuando ya no son necesarios. En este ejemplo se cierra el mensaje de solicitud, el contexto de solicitud, el canal y el agente de escucha.

El ejemplo de código siguiente muestra un servicio básico en el que un agente de escucha del canal recibe solo uno mensaje. Un servicio real sigue aceptando canales y recibiendo mensajes hasta que el servicio finalice.

using System;
using System.ServiceModel.Channels;
namespace ProgrammingChannels
{
class Service
{
static void RunService()
{
    //Step1: Create a custom binding with just TCP.
    BindingElement[] bindingElements = new BindingElement[2];
    bindingElements[0] = new TextMessageEncodingBindingElement();
    bindingElements[1] = new HttpTransportBindingElement();

    CustomBinding binding = new CustomBinding(bindingElements);

    //Step2: Use the binding to build the channel listener.
    IChannelListener<IReplyChannel> listener =
          binding.BuildChannelListener<IReplyChannel>(
             new Uri("http://localhost:8080/channelapp"),
           new BindingParameterCollection());

    //Step3: Listening for messages.
    listener.Open();
    Console.WriteLine(
           "Listening for incoming channel connections");
    //Wait for and accept incoming connections.
    IReplyChannel channel = listener.AcceptChannel();
    Console.WriteLine("Channel accepted. Listening for messages");
    //Open the accepted channel.
    channel.Open();
    //Wait for and receive a message from the channel.
    RequestContext request= channel.ReceiveRequest();
    //Step4: Reading the request message.
    Message message = request.RequestMessage;
    Console.WriteLine("Message received");
    Console.WriteLine($"Message action: {message.Headers.Action}");
    string data=message.GetBody<string>();
    Console.WriteLine($"Message content: {data}");
    //Send a reply.
    Message replymessage=Message.CreateMessage(
        binding.MessageVersion,
        "http://contoso.com/someotheraction",
         data);
    request.Reply(replymessage);
    //Step5: Closing objects.
    //Do not forget to close the message.
    message.Close();
    //Do not forget to close RequestContext.
    request.Close();
    //Do not forget to close channels.
    channel.Close();
    //Do not forget to close listeners.
    listener.Close();
}
public static void Main()
{
    Service.RunService();
    Console.WriteLine("Press enter to exit");
    Console.ReadLine();
}
}
}
Imports System.ServiceModel.Channels

Namespace ProgrammingChannels
    Friend Class Service

        Private Shared Sub RunService()

            'Step1: Create a custom binding with just TCP.
            Dim bindingElements(1) As BindingElement = {New TextMessageEncodingBindingElement(), _
                                                        New HttpTransportBindingElement()}

            Dim binding As New CustomBinding(bindingElements)

            'Step2: Use the binding to build the channel listener.         
            Dim listener = binding.BuildChannelListener(Of IReplyChannel)(New Uri("http://localhost:8080/channelapp"), _
                                                                          New BindingParameterCollection())

            'Step3: Listening for messages.
            listener.Open()
            Console.WriteLine("Listening for incoming channel connections")

            'Wait for and accept incoming connections.
            Dim channel = listener.AcceptChannel()
            Console.WriteLine("Channel accepted. Listening for messages")

            'Open the accepted channel.
            channel.Open()

            'Wait for and receive a message from the channel.
            Dim request = channel.ReceiveRequest()

            'Step4: Reading the request message.
            Dim message = request.RequestMessage
            Console.WriteLine("Message received")
            Console.WriteLine("Message action: {0}", message.Headers.Action)
            Dim data = message.GetBody(Of String)()
            Console.WriteLine("Message content: {0}", data)
            'Send a reply.
            Dim replymessage = Message.CreateMessage(binding.MessageVersion, _
                                                     "http://contoso.com/someotheraction", data)
            request.Reply(replymessage)
            'Step5: Closing objects.
            'Do not forget to close the message.
            message.Close()
            'Do not forget to close RequestContext.
            request.Close()
            'Do not forget to close channels.
            channel.Close()
            'Do not forget to close listeners.
            listener.Close()
        End Sub

        Public Shared Sub Main()

            Service.RunService()
            Console.WriteLine("Press enter to exit")
            Console.ReadLine()

        End Sub

    End Class
End Namespace