共用方式為


服務通道層級的程式設計

本主題說明如何撰寫 Windows Communication Foundation (WCF) 服務應用程式,而不使用 System.ServiceModel.ServiceHost 類別及其相關的物件模型。

接收訊息

以下為準備接收和處理訊息時所需的步驟:

  1. 建立繫結。

  2. 建置通道接聽程式。

  3. 開啟通道接聽程式。

  4. 讀取要求並傳送回覆。

  5. 關閉所有通道物件。

建立繫結。

接聽與接收訊息的第一步,就是建立繫結。WCF 隨附幾個內建或系統提供的繫結,您可以產生其中一項來直接使用。此外,您也可以產生 CustomBinding 類別來建立自己的自訂繫結 (清單 1 中的程式碼也會執行相同作業)。

下列的程式碼範例會建立 System.ServiceModel.Channels.CustomBinding 的執行個體,並將 System.ServiceModel.Channels.HttpTransportBindingElement 新增至其項目集合 (用來建置通道堆疊的繫結項目集合)。在此範例中,由於項目集合只具有 HttpTransportBindingElement,因此結果通道堆疊也只有 HTTP 傳輸通道。

建置 ChannelListener

在建立繫結後,我們可以呼叫 System.ServiceModel.Channels.Binding.BuildChannelListener.Uri,System.ServiceModel.Channels.BindingParameterCollection) 來建置通道接聽程式,其中的型別參數就是要建立的通道類型。在此範例中,我們會使用 System.ServiceModel.Channels.IReplyChannel,因為我們想要以要求/回覆訊息交換模式來接聽傳入訊息。

IReplyChannel 會被用來接收要求訊息與傳回回覆訊息。呼叫 System.ServiceModel.Channels.IReplyChannel.ReceiveRequest 會傳回 System.ServiceModel.Channels.IRequestChannel,以便用來接收要求訊息並傳回回覆訊息。

在建立接聽程式時,我們會傳送接聽程式所接聽的網路位址,在此範例為 https://localhost:8080/channelapp。一般來說,每個傳輸通道都支援一到數個位址配置,例如,HTTP 傳輸同時支援 http 和 https 配置。

在建立接聽程式時,我們同時會傳送空的 System.ServiceModel.Channels.BindingParameterCollection。繫結參數機制會負責將控制接聽程式建置方式的參數傳送出去。我們的範例並未使用此類參數,因此我們會傳送空的集合。

接聽傳入訊息

接著,我們會在接聽程式上呼叫 System.ServiceModel.ICommunicationObject.Open 並開始接受通道。System.ServiceModel.Channels.IChannelListener.AcceptChannel 的行為將視傳輸為連線導向還是沒有連線模式而定。如果是連線導向傳輸,AcceptChannel 會在新的連線要求進入時才停止封鎖,這時它會傳回一個代表該項新連線的新通道。如果是沒有連線的傳輸,例如 HTTP,則 AcceptChannel 會立即傳回由傳輸接聽程式所建立,且是唯一的通道。

在此範例中,接聽程式會傳回可實作 IReplyChannel 的通道。為了在此通道上接收訊息,首先我們必須在其上呼叫 System.ServiceModel.ICommunicationObject.Open,以將之轉換成準備通訊的狀態。接著我們會呼叫 ReceiveRequest 並在訊息抵達之前進行封鎖。

讀取要求並傳送回覆

ReceiveRequest 傳回 RequestContext,我們會透過其 RequestMessage 屬性來取回接收的訊息。我們會寫出訊息的行動與本文內容 (我們假定是字串)。

在此情況下,為了傳送回覆,我們會建立新的回覆訊息並傳回要求中所收到的字串資料。接著,我們會呼叫 Reply 來傳送回覆訊息。

關閉物件

為避免洩漏資源,請在不再需要時,關閉通訊期間所使用的物件,這點請您務必注意。在此範例中,我們會關閉要求訊息、要求內容、通道和接聽程式。

下列程式碼範例示範基本服務,其中的通道接聽程式只會收到一個訊息。真實的服務會在服務結束之前持續接受通道並接收訊息。

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("https://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, 
        "https://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();
}
}
}