Dela via


Programmering på servicekanalnivå

Det här avsnittet beskriver hur du skriver ett WCF-tjänstprogram (Windows Communication Foundation) utan att använda System.ServiceModel.ServiceHost och dess associerade objektmodell.

Ta emot meddelanden

För att vara redo att ta emot och bearbeta meddelanden krävs följande steg:

  1. Skapa en bindning.

  2. Skapa en kanallyssnare.

  3. Öppna kanallyssnaren.

  4. Läs begäran och skicka ett svar.

  5. Stäng alla kanalobjekt.

Skapa en bindning

Det första steget i att lyssna efter och ta emot meddelanden är att skapa en bindning. WCF levereras med flera inbyggda eller systembaserade bindningar som kan användas direkt genom att instansiera en av dem. Dessutom kan du också skapa en egen anpassad bindning genom att instansiera en CustomBinding-klass, vilket är vad koden i listning 1 gör.

Kodexemplet nedan skapar en instans av System.ServiceModel.Channels.CustomBinding och lägger till en System.ServiceModel.Channels.HttpTransportBindingElement i dess Elements-samling som är en samling bindningselement som används för att skapa kanalstacken. I det här exemplet, eftersom elementsamlingen bara HttpTransportBindingElementhar , har den resulterande kanalstacken endast HTTP-transportkanalen.

Skapa en ChannelListener

När du har skapat en bindning anropar Binding.BuildChannelListener vi för att skapa kanallyssningsverktyget där typparametern är kanalformen som ska skapas. I det här exemplet använder System.ServiceModel.Channels.IReplyChannel vi eftersom vi vill lyssna efter inkommande meddelanden i ett utbytesmönster för begäran/svarsmeddelanden.

IReplyChannel används för att ta emot begärandemeddelanden och skicka tillbaka svarsmeddelanden. Anrop IReplyChannel.ReceiveRequest returnerar ett System.ServiceModel.Channels.IRequestChannel, som kan användas för att ta emot begärandemeddelandet och för att skicka tillbaka ett svarsmeddelande.

När vi skapar lyssnaren skickar vi nätverksadressen som den lyssnar på, i det här fallet http://localhost:8080/channelapp. I allmänhet stöder varje transportkanal ett eller eventuellt flera adressscheman, till exempel http-transporten stöder både http- och https-scheman.

Vi skickar också en tom System.ServiceModel.Channels.BindingParameterCollection när du skapar lyssnaren. En bindningsparameter är en mekanism för att skicka parametrar som styr hur lyssnaren ska skapas. I vårt exempel använder vi inte några sådana parametrar så vi skickar en tom samling.

Lyssna efter inkommande meddelanden

Sedan anropar ICommunicationObject.Open vi lyssnaren och börjar acceptera kanaler. Beteendet IChannelListener<TChannel>.AcceptChannel för beror på om transporten är anslutningsorienterad eller anslutningslös. För anslutningsorienterade transporter blockeras AcceptChannel tills en ny anslutningsbegäran kommer in då den returnerar en ny kanal som representerar den nya anslutningen. För anslutningslösa transporter, till exempel HTTP, AcceptChannel returneras omedelbart med den enda kanal som transportlyssnaren skapar.

I det här exemplet returnerar lyssnaren en kanal som implementerar IReplyChannel. För att ta emot meddelanden på den här kanalen anropar ICommunicationObject.Open vi först den för att placera den i ett tillstånd som är redo för kommunikation. Vi anropar ReceiveRequest sedan vilka block tills ett meddelande kommer.

Läsa begäran och skicka ett svar

När ReceiveRequest returnerar ett RequestContextfår vi det mottagna meddelandet med dess RequestMessage egenskap. Vi skriver ut meddelandets åtgärd och brödtextinnehåll (som vi antar är en sträng).

För att skicka ett svar skapar vi ett nytt svarsmeddelande i det här fallet som skickar tillbaka de strängdata som vi fick i begäran. Sedan anropar Reply vi för att skicka svarsmeddelandet.

Stänga objekt

För att undvika läckande resurser är det mycket viktigt att stänga objekt som används i kommunikationen när de inte längre behövs. I det här exemplet stänger vi begärandemeddelandet, begärandekontexten, kanalen och lyssnaren.

I följande kodexempel visas en grundläggande tjänst där en kanallyssnare bara tar emot ett meddelande. En riktig tjänst fortsätter att acceptera kanaler och ta emot meddelanden tills tjänsten avslutas.

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