閱讀目錄
一:前言
二:WCF服務的建立
三:託管WCF服務
四:WCF服務的調用
五:總結
一:前言
大家看到三個工程圖一,分別對應圖二裡面的不同部分,Client工程對應圖二裡面的Client,HelloWorldService工程對應了圖二裡面的Service,也就是說具體的服務是由HelloWorldService來進行提供的,Host工程對應圖二裡面的ServiceHost,要為HelloWorldService這個服務來提供一個啟動並執行環境
圖一
圖二
二:WCF服務的建立
下面咱們來看具體的工程裡面的代碼,第一個工程:HelloWorldService,也就是服務建立的這個工程,為了能夠使用WCF,在引用裡面需要添加System.ServiceModel和System.IdentityModel這兩個命名空間
在這個介面中實際上是定義了我們這個服務它要完成哪些事情,在這個介面中它要完成GetHelloWorld這個操作並且要有一個字串類型的傳回值,大家看到在介面上面多了一些屬性ServiceContract和OperationContract,這些屬性是在WCF當中特有的一些標記,這些標記我們把它稱之為契約,這個實際上是WCF一個非常顯著的特點,在WCF當中來說用戶端與服務端進行通訊必須要遵循某個契約來完成,用戶端和服務端保證這些契約必須是相吻合的
1:IHelloWorldService.cs
using System;
using System.ServiceModel;
namespace HelloWorldService
{
/*加了契約的介面*/
[ServiceContract(Namespace="http://www.monkeyfu.net/")]
public interface IHelloWorldService
{
[OperationContract]
string GetHelloWorld();
}
}
2:HelloWorldService.cs
namespace HelloWorldService
{
/*來實現這個介面的一個具體類,對於加了契約的介面來進行實現*/
class HelloWorldService:IHelloWorldService
{
public string GetHelloWorld()
{
return string.Format("訊息收到了在{0}:{1}", DateTime.Now, "世界如此美好,我卻如此暴躁,不好,不好!");
}
}
}
三:託管WCF服務
第二個工程:Host,為了能夠給客戶提供服務的話,這個Service必然要被執行,它被執行的時候必然要放到主機裡面,也就是必然要放到服務的主機裡面,也就是ServiceHost裡面來進行執行
1:建立主機
在Main這個主函數裡面,我們建立一個ServiceHost host = new ServiceHost(),也就是建立一個主機,並且這個host所對應的服務執行個體是HelloWorldService.HelloWorldService也就是第一個工程裡面的實現那個類,ServiceHost host = new ServiceHost(typeof(HelloWorldService.HelloWorldService))這句代碼的意思就是說我們啟動了一個新的主機,這個主機裡面現在運行著一個服務,這個服務是由HelloWorldService.HelloWorldService這個類來進行實現的
2:添加新的Endpoint
然後在建立完一個host我們需要添加一個新的Endpoint,之前我們說過Endpoint叫端點也叫終結點,它的主要作用是用來提供Service向外發布的介面以實現用戶端和服務端之間的通訊,在我們添加一個新的Endpoint需要指定一些參數,第一個參數是這個Endpoint綁定到了哪個介面上,在這裡是綁定到了IHelloWorldService這個介面上面,也就是說所有經過這個Endpoint的訊息它都是遵循這個介面的,也就意味著所有通過我們添加的這個Endpoint的訊息必須都要滿足IHelloWorldService介面裡面相應的契約當中的要求,第二個參數還要指定我們的這個Endpoint傳輸訊息的時候需要綁定在哪個協議上面,在這裡是使用new NetTcpBinding(), 就是使用TCP的協議來進行訊息的傳遞,在指定完協議綁定完以後,第三個參數是要指定我們在進行訊息傳遞的時候,通訊的具體地址是哪裡,在這裡是net.tcp://localhost:9000/HelloWorldService
3:開啟主機
然後host.Open();是開啟主機,當host開啟後可以對來提供服務了,用戶端也可以連到主機上面來使用主機上面提供的這個HelloWorldService的這個服務了
1:Program.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using HelloWorldService;
namespace Host
{
class Program
{
static void Main(string[] args)
{
//step1啟動了一個新的主機,這個主機裡面現在運行著一個服務
using (ServiceHost host = new ServiceHost(typeof(HelloWorldService.HelloWorldService)))
{
//step2用來提供Service向外發布的介面以實現用戶端和服務端之間的通訊
host.AddServiceEndpoint(typeof(IHelloWorldService), new NetTcpBinding(), "net.tcp://localhost:9000/HelloWorldService");
//step3開啟主機
host.Open();
Console.ReadLine();
}
}
}
}
四:WCF服務的調用
第三個工程:Client
1:建立Proxy代理
前面講到Client它想要與Service進行互動的話需要一個Proxy代理,因此我們首先需要建立一個Proxy,我們使用ChannelFactory通道廠類建立一個新的channel通道出來,ChannelFactory它本身是一個泛型,在這個泛型指明這個Proxy遵循了哪一個契約,在這裡我們使用了IHelloWorldService這個契約,這個契約的描述我們定義在了class Program的上面,大家可以看到這個描述和我們定義的IHelloWorldService描述是一摸一樣的,用戶端要想使用這個服務的話,必須使用和這個服務相匹配的契約來進行訪問,這個是必須要遵守的要求,CreateChannel(new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:9000/HelloWorldService"))在CreateChannel方法裡面來指定一些通訊相關的參數,第一個參數也是綁定在Tcp上面的通訊方法,第二個參數是建立一個新的EndpointAddress,並且它的地址是指向ServiceHost的地址,大家會看到當我們建立完Proxy代理以後,實際上是把我們的Client端和Host端建立的一個等價的聯絡,這個聯絡就是我們大家都是使用Tcp協議,來訪問Host提供的地址net.tcp://localhost:9000/HelloWorldService,並且使用相同的契約
2:通過代理訪問服務
在建立完Proxy代理以後,我們就可以調用Proxy代理裡面的GetHelloWorld這個方法了,這個GetHelloWorld就是前面的IHelloWorldService介面提供的方法,在執行GetHelloWorld的這個方法時候,WCF會通過Tcp協議來訪問Host裡面的net.tcp://localhost:9000/HelloWorldService這個地址,在Host端的Endpoint會接收到這個訊息以後會根據契約IHelloWorldService找到HelloWorldService類裡面相應的商務邏輯,並且執行邏輯裡面實際的代碼,對於用戶端這些底層我們不需要去關心的,我們只需要調用GetHelloWorld這個方法就行了,跟我們本地調用是沒什麼區別的,其實就是通過代理類完成類似本地調用實現了分布式調用
1:Program.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
namespace Client
{
//step1建立服務契約的一個副本
[ServiceContract(Namespace = "http://www.monkeyfu.net/")]
public interface IHelloWorldService
{
[OperationContract]
string GetHelloWorld();
}
class Program
{
static void Main(string[] args)
{
//step2建立Proxy代理
IHelloWorldService proxy = ChannelFactory<IHelloWorldService>.CreateChannel(new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:9000/HelloWorldService"));
//step3通過代理訪問服務
string Result = proxy.GetHelloWorld();
Console.WriteLine(Result);
Console.ReadLine();
}
}
}
運行時效果
Client端通過Tcp協議去訪問了Host端裡面的HelloWorldService服務裡面的GetHelloWorld這個方法, 這樣我們就完成了一個簡單的基於Tcp協議的分布式的調用
1:首先啟動Host端
2:然後啟動Client端
五:總結
用戶端和服務端的基本要求
. 服務端
1:定義和實現服務契約
就是說在服務這一端的話,它不但要完成具體服務的商務邏輯,還要完成這個服務相應的契約
2:為服務類型建立ServiceHost執行個體,暴露Endpoint
建立ServiceHost執行個體可以理解為我們建立了一個伺服器,並且把這個服務放到伺服器裡來進行處理,同時要暴露出Endpoint端點來,使得用戶端能夠來訪問ServiceHost裡面對應的Service服務
3:開啟通訊的通道
使得用戶端能夠訪問服務端的這些服務
. 用戶端
1:需要服務契約的一個副本和關於Endpoints端點的資訊
服務契約的一個副本可以理解為在這個服務當中包含契約的一個介面,雖然說用戶端不需要服務的具體的商務邏輯,但是用戶端需要這個服務當中包含契約的一個介面,來告訴用戶端它如何與服務端進行通訊應該遵循哪些規則,Endpoint端點的資訊主要包含了伺服器端服務的具體地址以及使用什麼樣的協議進行具體的通訊
2:為特定的Endpoints構建通訊通道並且執行叫用作業已完成我們具體的服務
下面這個圖三更好的說明了用戶端和服務端具體的Endpoint的一個作用
我們就以ABC來進行一下闡述,一個訊息要想傳送出去或者想要接收到的話必須要有ABC這三樣東西的,這三樣是缺一不可的
-A表示Address地址,這個主機在哪,像上面提到的”net.tcp://localhost:9000/HelloIndigo“,這個就是我們所說的地址,它告訴用戶端要去哪裡訪問主機當中的服務
-B表示Binding綁定,Binding告訴我們如何來進行通訊,像上面提到的我們使用的Tcp的協議來進行通訊
-C表示Contract契約,Contract告訴我們究竟要傳什麼,要幹什麼,還對我們要幹什麼的操作進行了具體的約束,我們做這件事情的名稱和參數都是用Contract契約來描述的
圖三