Delen via


Service Channel-Level Programmeren

In dit onderwerp wordt beschreven hoe u een WCF-servicetoepassing (Windows Communication Foundation) schrijft zonder de System.ServiceModel.ServiceHost en het bijbehorende objectmodel te gebruiken.

Berichten ontvangen

Als u klaar wilt zijn voor het ontvangen en verwerken van berichten, zijn de volgende stappen vereist:

  1. Maak een binding.

  2. Bouw een kanaalluistelement.

  3. Open de kanaallijstunaar.

  4. Lees de aanvraag en verzend een antwoord.

  5. Sluit alle kanaalobjecten.

Een binding maken

De eerste stap bij het luisteren naar en ontvangen van berichten is het maken van een binding. WCF wordt geleverd met verschillende ingebouwde of door het systeem geleverde bindingen die rechtstreeks kunnen worden gebruikt door een van deze bindingen te instantiëren. Daarnaast kunt u ook uw eigen aangepaste binding maken door een CustomBinding-klasse te instantiëren. Dit is wat de code in vermelding 1 doet.

In het onderstaande codevoorbeeld wordt een exemplaar van System.ServiceModel.Channels.CustomBinding gemaakt en wordt een System.ServiceModel.Channels.HttpTransportBindingElement toegevoegd aan de elementenverzameling. Dit is een verzameling bindingselementen die worden gebruikt om de kanaalstack te bouwen. In dit voorbeeld, omdat de elementenverzameling alleen de HttpTransportBindingElementheeft, heeft de resulterende kanaalstack alleen het HTTP-transportkanaal.

Een ChannelListener bouwen

Nadat we een binding hebben gemaakt, roepen we Binding.BuildChannelListener aan om de kanaallistener te bouwen, waarbij de typeparameter de vorm van het kanaal specificeert dat moet worden gemaakt. In dit voorbeeld gebruiken we System.ServiceModel.Channels.IReplyChannel omdat we willen luisteren naar binnenkomende berichten in een aanvraag-/antwoordberichtuitwisselingspatroon.

IReplyChannel wordt gebruikt voor het ontvangen van aanvraagberichten en het verzenden van antwoordberichten. Bij het bellen van IReplyChannel.ReceiveRequest wordt een System.ServiceModel.Channels.IRequestChannelgeretourneerd, die kan worden gebruikt voor het ontvangen van het aanvraagbericht en het terugsturen van een antwoordbericht.

Bij het maken van de listener geven we het netwerkadres door waarop het luistert, in dit geval http://localhost:8080/channelapp. Over het algemeen ondersteunt elk transportkanaal een of mogelijk verschillende adresschema's, bijvoorbeeld het HTTP-transport ondersteunt zowel http- als https-schema's.

We geven ook een lege System.ServiceModel.Channels.BindingParameterCollection door bij het maken van de listener. Een bindingsparameter is een mechanisme om parameters door te geven die bepalen hoe de listener moet worden gebouwd. In ons voorbeeld gebruiken we geen dergelijke parameters, zodat we een lege verzameling doorgeven.

Luisteren naar binnenkomende berichten

Vervolgens bellen we ICommunicationObject.Open op de listener en beginnen met het accepteren van kanalen. Het gedrag van IChannelListener<TChannel>.AcceptChannel is afhankelijk van het feit of het transport verbindingsgeoriënteerd of verbindingsloos is. Voor verbindingsgeoriënteerde transporten wordt AcceptChannel geblokkeerd totdat een nieuwe verbindingsaanvraag binnenkomt op welk moment een nieuw kanaal wordt geretourneerd dat de nieuwe verbinding vertegenwoordigt. Voor transporten met minder verbindingen, zoals HTTP, retourneert AcceptChannel onmiddellijk met het ene kanaal dat de transportlistener maakt.

In dit voorbeeld retourneert de listener een kanaal dat IReplyChannelimplementeert. Als u berichten op dit kanaal wilt ontvangen, roepen we eerst ICommunicationObject.Open aan om het kanaal gereed te maken voor communicatie. Vervolgens bellen we ReceiveRequest die blokkeert totdat er een bericht binnenkomt.

De aanvraag lezen en een antwoord verzenden

Wanneer ReceiveRequest een RequestContextretourneert, krijgen we het ontvangen bericht met behulp van de eigenschap RequestMessage. We schrijven de actie- en hoofdtekstinhoud van het bericht op (waarvan we aannemen dat het een tekenreeks is).

Als u een antwoord wilt verzenden, maken we in dit geval een nieuw antwoordbericht dat de tekenreeksgegevens doorgeeft die we in de aanvraag hebben ontvangen. Vervolgens bellen we Reply om het antwoordbericht te verzenden.

Objecten sluiten

Om te voorkomen dat resources worden gelekt, is het erg belangrijk om objecten die worden gebruikt in communicatie te sluiten wanneer ze niet meer nodig zijn. In dit voorbeeld sluiten we het aanvraagbericht, de aanvraagcontext, het kanaal en de listener.

In het volgende codevoorbeeld ziet u een basisservice waarin een kanaallistener slechts één bericht ontvangt. Een echte service blijft kanalen accepteren en berichten ontvangen totdat de service wordt afgesloten.

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