1. 程式人生 > >網路程式設計之WCF程式設計:WCF服務和客戶端的建立,回撥

網路程式設計之WCF程式設計:WCF服務和客戶端的建立,回撥

1.概念

Windows Communication Foundation(WCF)是由微軟發展的一組資料通訊的應用程式開發介面,可以翻譯為Windows通訊介面。它是.NET框架的一部分,由 .NET Framework 3.0 開始引入。

WCF的終結點有三個要素組成,分別是地址(Address)、繫結(Binding)和契約(Contract),簡記可寫成Endpoint = ABC。
 地址:地址決定了服務的位置,解決了服務定址的問題。
 繫結:繫結實現了通訊的所有細節,包括網路傳輸、訊息編碼,以及其他為實現某種功能對訊息進行的相應處理。繫結的型別包括BasicHttpBinding、WsHttpBinding、NetTcpBinding等。


 契約:契約是對服務操作的抽象,也是對訊息交換模式以及訊息結構的定義。

2.契約

WCF 的基本概念是以契約(Contract) 來定義雙方溝通的協議,契約必須要以介面的方式來體現,而實際的服務程式碼必須要由這些合約介面派生並實現。契約分成了四種: 資料契約 (Data Contract),訂定雙方溝通時的資料格式。服務契約 (Service Contract),訂定服務的定義。操作契約 (Operation Contract),訂定服務提供的方法。訊息契約 (Message Contract),訂定在通訊期間改寫訊息內容的規範。

如下圖,解釋了契約:

3.繫結

由於 WCF 支援了

HTTPTCP,Named Pipe,MSMQ,Peer-To-Peer TCP 等協議,而 HTTP 又分為基本 HTTP 支援 (BasicHttpBinding) 以及 WS-HTTP 支援 (WsHttpBinding),而 TCP 亦支援 NetTcpBinding,NetPeerTcpBinding 等通訊方式,因此,雙方必須要統一通訊的協議,並且也要在編碼以及格式上要有所一致。

 基本繫結(BasicHttpBinding)

對應BasicHttpBinding類,能夠將WCF服務公開為傳統的ASMX Web服務,是以前就的程式能夠使用現在的WCF服務。在實際開發中一個WCF服務可能會給不同的程式呼叫,如給Java的程式呼叫,給Flex的程式呼叫等,那麼採用BasicHttpBinding最合適不過了

TCP繫結(NetTcpBinding)

對應與NetTcpBinding類,TCP繫結使用TCP協議在Intranet中跨機器的通訊,注意這裡是Intranet而非Internet。支援多種特性,包括可靠性、事務性、安全性、以及WCF之間通訊的優化。前提是要求客戶端與服務端都必須使用WCF

4.程式設計

第一步:wcf服務端

新建一個“windows窗體程式”名稱為WCFHostServer,然後新增一個“WCF服務”名稱為Service1

給窗體取名為FormService,然後在窗體的Load事件中編寫程式碼啟動wcf服務:NetTcpBinding方式啟動wcf服務和BasicHttpBinding方式啟動wcf服務

ServiceHost m_ServiceHost;
private void Form1_Load(object sender, EventArgs e)
{
     //NetTcpBinding方式啟動wcf服務
      m_ServiceHost = new ServiceHost(typeof(Service1));//Service1是wcf服務的類名稱
      NetTcpBinding binding = new NetTcpBinding();
     Uri baseAddress = new Uri(string.Format("net.tcp://localhost:10086/WCFHostServer/Service1"));
     m_ServiceHost.AddServiceEndpoint(typeof(IService1), binding, baseAddress);
     //BasicHttpBinding方式啟動wcf服務
      ServiceMetadataBehavior metadataBehavior;
     metadataBehavior = m_ServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
     if (metadataBehavior == null)
     {
          metadataBehavior = new ServiceMetadataBehavior();
          metadataBehavior.HttpGetEnabled = true;
          metadataBehavior.HttpGetUrl = new Uri(string.Format("http://localhost:10085/WCFHostServer/Service1"));
          m_ServiceHost.Description.Behaviors.Add(metadataBehavior);
     }
     m_ServiceHost.Open();
}

在窗體的Closeing中編寫服務退出程式碼

private void FormService_FormClosing(object sender, FormClosingEventArgs e)
{
     if (m_ServiceHost != null)
     {
          m_ServiceHost.Close();
          m_ServiceHost = null;
     }
}

在 IService1.cs中增加一個方法GetSvrTime

 在Service1.cs中實現介面的方法GetSvrTime,獲取伺服器時間

第二步:WCF客戶端

新建一個“windows窗體程式”命名為WCFHostClient,在Debug中執行WCFHostServer窗體(這一步很重要),然後在專案WCFHostClient中右鍵--》“新增服務引用”,在地址填入以BasicHttpBinding繫結方式啟動wcf服務的地址http://localhost:10085/WCFHostServer/Service1,點選“前往”,然後連線上後點擊“確定”,在WCFHostClient專案中就會增加一個Service References(ServiceReference1)

 將窗體命名為FormClient.cs,在窗體上增加兩個textbox(ip為textbox1,port為textbox2)和一個button,如下圖:

在button中增加wcf客戶端連線wcf服務端的程式碼

private void button1_Click_1(object sender, EventArgs e)
{
          //basicHttpBinding繫結方式的通訊 單工
            Service1Client host = new ServiceReference1.Service1Client();
          string htime = host.GetSvrTime();//呼叫GetSvrTime獲取到wcf伺服器上的時間
          MessageBox.Show("basicHttpBinding" + "@" + htime);

          //NetTcpBinding繫結方式的通訊 雙工
            IService1 m_Innerclient;
           ChannelFactory<IService1> m_ChannelFactory;
           NetTcpBinding binding = new NetTcpBinding();
           Uri baseAddress = new Uri(string.Format("net.tcp://{0}:{1}/WCFHostServer/Service1",textBox1.Text, textBox2.Text));
           m_ChannelFactory=new ChannelFactory<IService1>( binding, new EndpointAddress(baseAddress));
           m_Innerclient = m_ChannelFactory.CreateChannel();
           string htime1=m_Innerclient.GetSvrTime();//呼叫GetSvrTime獲取到wcf伺服器上的時間
           MessageBox.Show("NetTcpBinding" + "@" + htime1);
}

上面的程式碼是客戶端呼叫服務端提供的介面GetSvrTime來通訊的,那麼服務端如果發生了一個事件想主動通知客戶端,又不可能反向呼叫客戶端提供的介面,這時候就需要使用回撥的方式進行wcf通訊了,也就是說服務端定義一個回撥,客戶端註冊這個回撥,然後就可以在這個回撥裡等待服務端的資訊通知了

第三步:服務端回撥通知客戶端資訊

wcf服務端WCFHostServer步驟

1.在IService1.cs中增加一個回撥介面ISvrToCliCallBack,增加方法NotifyClientMsg,設定該方法為單向,如圖:


 2.Service1.cs中在客戶端呼叫方法GetSvrTime的時候獲取ISvrToCliCallBack的例項


注意: 使用OperationContext.Current來獲取當前客戶端操作的例項只有在客戶端呼叫服務端提供的介面的時候才能有效,否則為NULL

 所以OperationContext.Current.GetCallbackChannel必須在GetSvrTime裡實現

3.在FormServer窗體上增加一個按鈕,點選該按鈕實現通知客戶端的功能


 在button增加下面程式碼

 private void button1_Click(object sender, EventArgs e)
 {
     Service1.userCallBack.NotifyClientMsg("服務端給客戶端通知啦");
 }
呼叫NotifyClientMsg通知客戶端

wcf客戶端WCFHostClient步驟:

1.在Debug目錄中開啟WCFHostServer.exe,客戶端在ServiceReference1更新服務引用

2.在FormClient中繼承介面IService1Callback,實現方法NotifyClientMsg


也就是說,當服務端有資訊通知的時候(點選FromServer上面的“通知客戶端”按鈕)客戶端的這個方法就會啟用

3.在FormClient_Load中使用雙工繫結方式NetTcpBinding來連線wcf服務(注:不能使用單工方式basicHttpBinding)

IService1 m_Innerclient;

 

注意:這裡要使用雙工通道DuplexChannelFactory,而不是ChannelFactory

4.向wcf服務註冊客戶端操作的例項

 m_Innerclient.GetSvrTime();
這句可以放在Form_load最後,也就是連線完wcf服務之後進行

以上wcf服務端和客戶端都完成了,客戶端和服務端程式執行後,點選服務端窗體的“通知客戶端”,客戶端就會彈出窗體