Partager via


Programmation du service Channel-Level

Cette rubrique explique comment écrire une application de service Windows Communication Foundation (WCF) sans utiliser le modèle objet associé et sans recourir à System.ServiceModel.ServiceHost.

réception de messages

Pour être prêt à recevoir et traiter des messages, les étapes suivantes sont requises :

  1. Créer une liaison.

  2. Créez un écouteur de canal.

  3. Ouvrez l’écouteur de canal.

  4. Lisez la demande et envoyez une réponse.

  5. Fermer tous les objets de canal.

Création d’une liaison

La première étape de l’écoute et de la réception des messages consiste à créer une liaison. WCF est fourni avec plusieurs liaisons intégrées ou fournies par le système qui peuvent être utilisées directement ou par instanciation. En outre, vous pouvez également créer votre propre liaison personnalisée en instanciant une classe CustomBinding qui est ce que fait le code dans la liste 1.

L’exemple de code ci-dessous crée une instance de System.ServiceModel.Channels.CustomBinding et ajoute une System.ServiceModel.Channels.HttpTransportBindingElement à sa collection Elements, qui est une collection d’éléments de liaison utilisés pour générer la pile de canaux. Dans cet exemple, étant donné que la collection d’éléments n’a que le HttpTransportBindingElementcanal de transport HTTP, la pile de canaux résultante n’a que le canal de transport HTTP.

Génération d’un ChannelListener

Après avoir créé une liaison, nous appelons Binding.BuildChannelListener pour générer l'écouteur de canal où le paramètre de type est la forme de canal à créer. Dans cet exemple, nous utilisons System.ServiceModel.Channels.IReplyChannel parce que nous voulons écouter les messages entrants dans un modèle d’échange de messages de demande/réponse.

IReplyChannel est utilisé pour recevoir des messages de demande et renvoyer des messages de réponse. L’appel IReplyChannel.ReceiveRequest retourne un System.ServiceModel.Channels.IRequestChannel, qui peut être utilisé pour recevoir le message de demande et renvoyer un message de réponse.

Lors de la création de l’écouteur, nous transmettons l’adresse réseau sur laquelle elle écoute, dans ce cas http://localhost:8080/channelapp. En général, chaque canal de transport prend en charge un ou plusieurs schémas d’adresse, par exemple, le transport HTTP prend en charge les schémas http et https.

Nous passons également un System.ServiceModel.Channels.BindingParameterCollection vide lors de la création de l'écouteur. Un paramètre de liaison est un mécanisme permettant de transmettre des paramètres qui contrôlent la façon dont l’écouteur doit être généré. Dans notre exemple, nous n’utilisons aucun paramètre de ce type, nous transmettons donc une collection vide.

Écoute des messages entrants

Nous appelons ensuite ICommunicationObject.Open sur l'écouteur et nous commençons à accepter des canaux. Le comportement de IChannelListener<TChannel>.AcceptChannel varie selon que le transport est orienté vers la connexion ou non orienté vers la connexion. Pour les transports orientés connexion, AcceptChannel se bloque jusqu'à ce qu'une nouvelle demande de connexion arrive, auquel point il retourne un nouveau canal qui représente cette nouvelle connexion. Pour les transports sans connexion, tels que HTTP, AcceptChannel renvoie immédiatement avec l'unique canal créé par l'écouteur de transport.

Dans cet exemple, l’écouteur renvoie un canal implémentant IReplyChannel. Pour recevoir des messages sur ce canal, nous appelons d'abord ICommunicationObject.Open pour le mettre dans un état prêt pour la communication. Ensuite, nous appelons ReceiveRequest, ce qui bloque jusqu'à ce qu'un message arrive.

Lecture de la demande et envoi d’une réponse

Lorsque ReceiveRequest retourne un RequestContext, nous récupérons le message reçu grâce à sa propriété RequestMessage. Nous écrivons l’action et le contenu du corps du message (que nous supposons est une chaîne).

Pour envoyer une réponse, nous créons un nouveau message de réponse en renvoyant les données textuelles que nous avons reçues dans la demande. Ensuite, nous appelons Reply pour envoyer le message de réponse.

Fermeture des objets

Pour éviter la fuite de ressources, il est très important de fermer les objets utilisés dans les communications lorsqu’ils ne sont plus nécessaires. Dans cet exemple, nous fermons le message de requête, le contexte de la requête, le canal et l’écouteur.

L’exemple de code suivant montre un service de base dans lequel un écouteur de canal ne reçoit qu’un seul message. Un vrai service continue d’accepter des canaux et de recevoir des messages jusqu’à ce que le service se termine.

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