Delen via


Programmeren op servicekanaalniveau

In dit onderwerp wordt beschreven hoe u een WCF-servicetoepassing (Windows Communication Foundation) schrijft zonder het System.ServiceModel.ServiceHost 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 kanaallistener.

  3. Open de kanaallistener.

  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 gemaakt van System.ServiceModel.Channels.CustomBinding en wordt er 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 HttpTransportBindingElementresulterende kanaalstack heeft, heeft alleen het HTTP-transportkanaal.

Een ChannelListener bouwen

Nadat u een binding hebt gemaakt, wordt aangeroepen Binding.BuildChannelListener om de kanaallistener te bouwen waarbij de typeparameter de kanaalshape is die moet worden gemaakt. In dit voorbeeld gebruiken System.ServiceModel.Channels.IReplyChannel we omdat we willen luisteren naar binnenkomende berichten in een patroon voor het uitwisselen van aanvragen/beantwoorden van berichten.

IReplyChannel wordt gebruikt voor het ontvangen van aanvraagberichten en het terugsturen van antwoordberichten. Bellen IReplyChannel.ReceiveRequest retourneert een System.ServiceModel.Channels.IRequestChannel, dat kan worden gebruikt om het aanvraagbericht te ontvangen en een antwoordbericht terug te sturen.

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 roepen ICommunicationObject.Open we de listener op en beginnen met het accepteren van kanalen. Het gedrag is afhankelijk van IChannelListener<TChannel>.AcceptChannel of het transport verbindingsgeoriënteerd of verbindingsloos is. Voor verbindingsgeoriënteerde transporten AcceptChannel worden blokken geblokkeerd totdat een nieuwe verbindingsaanvraag binnenkomt op welk punt het een nieuw kanaal retourneert dat de nieuwe verbinding vertegenwoordigt. Voor transporten met minder verbindingen, zoals HTTP, AcceptChannel wordt direct geretourneerd met het ene kanaal dat de transportlistener maakt.

In dit voorbeeld retourneert de listener een kanaal dat wordt geïmplementeerd IReplyChannel. Om berichten op dit kanaal te ontvangen, roepen ICommunicationObject.Open we het eerst op om het in een status te plaatsen die gereed is voor communicatie. Vervolgens roepen ReceiveRequest we aan welke blokken totdat er een bericht binnenkomt.

De aanvraag lezen en een antwoord verzenden

Wanneer ReceiveRequest een RequestContextretourneert, ontvangen we het ontvangen bericht met behulp van RequestMessage de eigenschap. 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 Reply we 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: {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