Compartilhar via


Programação de nível por canal de serviço

Este tópico descreve como escrever um aplicativo do serviço WCF (Windows Communication Foundation) sem usar o System.ServiceModel.ServiceHost e o modelo de objeto associado.

recebendo mensagens

Para se preparar para receber e processar mensagens, as seguintes etapas são necessárias:

  1. Criar uma associação.

  2. Criar um ouvinte de canais.

  3. Abrir o ouvinte de canais.

  4. Ler a solicitação e enviar uma resposta.

  5. Fechar todos os objetos de canal.

Criar uma associação

A primeira etapa para escutar e receber mensagens é criar uma associação. O WCF é fornecido com várias associações internas ou fornecidas pelo sistema que podem ser usadas diretamente com a criação de uma instância de uma delas. Além disso, você também pode criar sua associação personalizada criando uma instância de uma classe CustomBinding, que é o que o código na listagem 1 faz.

O exemplo de código abaixo cria uma instância de System.ServiceModel.Channels.CustomBinding e adiciona uma System.ServiceModel.Channels.HttpTransportBindingElement à coleção Elements, que é uma coleção de elementos de associação que são usados para criar a pilha de canais. Neste exemplo, como a coleção de elementos só tem o HttpTransportBindingElement, pilha de canais resultante tem apenas o canal de transporte HTTP.

Como criar um ChannelListener

Depois de criar uma associação, chamamos Binding.BuildChannelListener para criar o ouvinte de canais, em que o parâmetro de tipo é a forma de canal a ser criada. Neste exemplo, estamos usando System.ServiceModel.Channels.IReplyChannel, porque queremos escutar as mensagens de entrada em um padrão de troca de mensagens de solicitação/resposta.

IReplyChannel é usado para receber mensagens de solicitação e enviar novamente mensagens de resposta. A chamada a IReplyChannel.ReceiveRequest retorna um System.ServiceModel.Channels.IRequestChannel, que pode ser usado para receber a mensagem de solicitação e para enviar novamente uma mensagem de resposta.

Ao criar o ouvinte, transmitimos o endereço de rede que ele escuta, nesse caso, http://localhost:8080/channelapp. Em geral, cada canal de transporte dá suporte a um ou a possivelmente vários esquemas de endereço, por exemplo, o transporte HTTP dá suporte a esquemas HTTP e HTTPS.

Também transmitimos uma System.ServiceModel.Channels.BindingParameterCollection vazia ao criar o ouvinte. Um parâmetro de associação é um mecanismo usado para transmitir parâmetros que controlam como o ouvinte deve ser criado. No exemplo, não estamos usando esses parâmetros, ou seja, transmitimos uma coleção vazia.

Como escutar as mensagens de entrada

Em seguida, chamamos ICommunicationObject.Open no ouvinte e começamos a aceitar canais. O comportamento de IChannelListener<TChannel>.AcceptChannel depende se o transporte é orientado à conexão ou sem conexão. Para os transportes orientados a conexão, AcceptChannel é bloqueado até que uma nova solicitação de conexão chegue e, nesse ponto, ele retorna um novo canal que representa essa nova conexão. Para os transportes sem conexão, como HTTP, AcceptChannel é retornado imediatamente com o único canal criado pelo ouvinte de transporte.

Neste exemplo, o ouvinte retorna um canal que implementa IReplyChannel. Para receber mensagens neste canal, primeiro, chamamos ICommunicationObject.Open nele para colocá-lo em um estado de preparação para a comunicação. Em seguida, chamamos ReceiveRequest, que é bloqueado até que uma mensagem chegue.

Como ler a solicitação e enviar uma resposta

Quando ReceiveRequest retorna um RequestContext, obtemos a mensagem recebida usando a propriedade RequestMessage dele. Gravamos a ação e o conteúdo do corpo da mensagem (que presumimos ser uma cadeia de caracteres).

Para enviar uma resposta, criamos uma mensagem de resposta, nesse caso, transmitindo novamente os dados de cadeia de caracteres que recebemos na solicitação. Em seguida, chamamos Reply para enviar a mensagem de resposta.

Como fechar objetos

Para evitar o vazamento de recursos, é muito importante fechar os objetos usados nas comunicações quando eles não são mais necessários. Neste exemplo, fechamos a mensagem de solicitação, o contexto da solicitação, o canal e o ouvinte.

O exemplo de código a seguir mostra um serviço básico no qual um ouvinte de canais recebe apenas uma mensagem. Um serviço real continua aceitando canais e recebendo mensagens até que o serviço seja encerrado.

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: {0}",
                          message.Headers.Action);
    string data=message.GetBody<string>();
    Console.WriteLine("Message content: {0}",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