WCF服務創建與使用(雙工模式)


昨天發布了《WCF服務創建與使用(請求應答模式)》,今天繼續學習與強化在雙工模式下WCF服務創建與使用,步驟與代碼如下。

第一步,定義服務契約(Service Contract),注意ServiceContract特性上需指定回調契約

//服務契約
using System.ServiceModel;

namespace WcfServiceLibrary1
{
    [ServiceContract(Namespace = "http://www.zuowenjun.cn",
     CallbackContract = typeof(ICallback))]
    public interface IHello
    {
        [OperationContract(IsOneWay = true)]
        void SetName(string name);
    }
}

//回調契約(由於回調契約本質也是一個服務契約,所以定義方式和一般意義上的服務契約基本一樣。
//有一點不同的是,由於定義服務契約時候已經通過[ServiceContract(CallbackContract=typeof(ICallback))]指明ICallback是一個服務契約了,所以ICallback不再需要添加ServiceContractAttribute特性)
using System.ServiceModel;

namespace WcfServiceLibrary1
{
    public interface ICallback
    {
        [OperationContract(IsOneWay = true)]
        void ShowHello(string name);
    }
}

第二步,實現服務契約,這里通過OperationContext.Current.GetCallbackChannel()獲取回調契約

using System.ServiceModel;

namespace WcfServiceLibrary1
{
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class HelloService:IHello
    {
        public void SetName(string name)
        {
            ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
            callback.ShowHello(name);
        }
    }
}


注意:ConcurrencyMode = ConcurrencyMode.Reentrant是設置並發模式,Reentrant與Multiple均可適用於多並發,默認是Single

第三步,創建服務寄宿程序,方法很多,我這里采取常用的配置方法

1.CONFIG文件配置部份:

(注: 1.在WCF預定義綁定類型中,WSDualHttpBinding和NetTcpBinding均提供了對雙工通信的支持,但是兩者在對雙工通信的實現機制上卻有本質的區別。WSDualHttpBinding是基於HTTP傳輸協議的;而HTTP協議本身是基於請求-回復的傳輸協議,基於HTTP的通道本質上都是單向的。WSDualHttpBinding實際上創建了兩個通道,一個用於客戶端向服務端的通信,而另一個則用於服務端到客戶端的通信,從而間接地提供了雙工通信的實現。而NetTcpBinding完全基於支持雙工通信的TCP協議。
2.若綁定類型采用NetTcpBinding,則地址應變更為:net.tcp://127.0.0.1:10800/HelloService,且不能有behaviorConfiguration配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      </service>
      <service name="WcfServiceLibrary1.HelloService">
        <endpoint address="http://127.0.0.1:10800/HelloService" binding="wsDualHttpBinding" contract="WcfServiceLibrary1.IHello"></endpoint>
      </service>
    </services>
  </system.serviceModel>
</configuration>

2.代碼部份:

using System;
using WcfServiceLibrary1;
using System.ServiceModel;
using System.ServiceModel.Description;


namespace ConsoleApplicationHost
{
    class Program
    {
        static void Main(string[] args)
        {
            BuildHelloServiceHostByConfig();
        }

        static void BuildHelloServiceHostByConfig()
        {
            using (ServiceHost host = new ServiceHost(typeof(HelloService)))
            {
                host.Opened += (s, e) => { Console.WriteLine("HelloService已經啟動,按按回車鍵終止服務!"); };
                host.Open();
                Console.ReadLine();
            }
        }
    }
}

第四步,客戶端程序調用WCF服務

注:在客戶端程序中首先需要創建或引用WCF服務類庫,然后創建實現回調契約的類

實現回調契約:

using System;
using WcfServiceLibrary1;

namespace ConsoleApplicationClient
{
    public class HelloCallBack:ICallback
    {
        public void ShowHello(string name)
        {
            Console.WriteLine("Hello! {0}.歡迎光臨IT文俊社區網,地址:www.zuowenjun.cn",name);
        }
    }
}


1.CONFIG文件配置部份:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
          <wsDualHttpBinding>
            <binding name="HelloServiceBinding" clientBaseAddress="http://127.0.0.1:10801/HelloServiceCallback"></binding>
          </wsDualHttpBinding>
        </bindings>
        <client>
          <endpoint name="HelloService" address="http://127.0.0.1:10800/HelloService" binding="wsDualHttpBinding" contract="WcfServiceLibrary1.IHello">
          </endpoint>
        </client>
    </system.serviceModel>
</configuration>

2.代碼部份:

using System;
using System.ServiceModel;
using WcfServiceLibrary1;

namespace ConsoleApplicationClient
{
    class Program
    {
        static void Main(string[] args)
        {
            CallHelloService();
            Console.WriteLine("按任意鍵結束。");
            Console.Read();
        }

        static void CallHelloService()
        {
            Console.Write("請輸入您的網名:");
            string input = Console.ReadLine();
            InstanceContext instanceContext = new InstanceContext(new HelloCallBack());
            using (DuplexChannelFactory<IHello> channel = new DuplexChannelFactory<IHello>(instanceContext, "HelloService"))
            {
                IHello proxy = channel.CreateChannel();
                using (proxy as IDisposable)
                {
                    proxy.SetName(input);
                    Console.ReadLine();//注意這句需保留,目的是為了阻止調用proxy的Dispose方法,因為該方法將會試圖關閉底層的TCP連接。由於服務端的回調操作也會使用該TCP連接,如果在回調操作尚未執行完畢就試圖關閉網絡連接,將會導致回調無法正常執行
                }
            }
        }
    }
}

 

這里特別說明一下,建議在定義服務方法時,若沒有返回值,建議為方法添加IsOneWay=True特性,可以使客戶端不用等待請求回復,雖然設置ConcurrencyMode = ConcurrencyMode.Reentrant,但若采用WINFORM客戶端使用,則會出現TIMEOUT錯誤,具體分析與解決方法,詳見:我的WCF之旅(6):在Winform Application中調用Duplex Service出現TimeoutException的原因和解決方案

說明:發表這篇文章參考了如下作者的文章:

我的WCF之旅(3):在WCF中實現雙工通信

 

文章同步發表於我的個人網站:http://www.zuowenjun.cn/post/2015/03/25/133.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM