學習了wcf一週了,趁着週末,記錄下來,溫故一下。不對的地方請多多指教!
一.WCF出現的背景
二.契約方法的同步,異步調用方式
三.WCF的無配置
一.WCF出現的背景
.net平臺下,有很多的分佈式技術
1. webservice 基於http協議的soap模式。。。
2. remoting 也是一種分佈式架構技術,常常用於tcp模式的二進制傳輸。。。
3. MSMQ 這是一種分佈式的離線式技術,用於業務解耦。
面對上面那3中需求,我們是不是需要整合一下,所以wcf應運而出了。
我們先理解以下慨念,方便我們對 wcf的理解
(1)ABC的概念
①:A:address:服務的地址
②:B:binding:client和service的通道,比如我們訪問web,我們使用http通道。 那麼wcf支持哪些通道呢?如:BasicHttpBinding,NetTcpBinding等等。
③:C:contract 我們定義的接口是怎麼樣的,參數,返回值,方法名。
(2)承載WCF的宿主:IIS,Console,winform
什麼是宿主呢?
WCF服務類不能憑空存在。每個WCF服務都必須託管(Hosting) 在Windows 進程中,該進程被稱爲宿主進程(Host Process)。單個宿主進程可以託管多個服務,而相同的服務類型也能夠託管在多個宿主進程中。
按我的理解應該是這樣的:假如A和B是兩個http地址,我們都在C公司上班(宿主),
去上班時我們可以從相同的門進入辦公室(port),也就是說,宿主相當於託管。
二.契約方法的同步,異步調用方式
(1)WCF中常見的三種綁定方式
1. basichttpbinding...
2. nettcpbinding...
3. netmsmqbinding...
net程序互通的binding, 一般都是netxxxxxbinding...
非net程序互通的binding. 一般都是wsxxxxbinding...
(2)契約中的調用方式。 client和servcie之間的調用方式。
1. 同步方式: 阻塞式方式【默認的調用方式】
Service端
public class FlyService : IFlyService { public string Fly(string message) { //阻塞5s Thread.Sleep(5000); Console.WriteLine("接收了Fly消息:{0}-{1}",message,DateTime.Now); return message+DateTime.Now; } }
Client
ServiceReference1.FlyServiceClient flyClient = new ServiceReference1.FlyServiceClient(); Console.WriteLine("開始調用:{0}",DateTime.Now); string res = flyClient.Fly("Hello World"); Console.WriteLine("結束調用:{0}",res);
2. 異步方式:
①第一種異步方式:開一個線程來訪問WCF
Task.Factory.StartNew(() => { string res = flyClient.Fly("Hello World"); Console.WriteLine("子線程訪問:{0}",res); });
運行結果我就不上傳圖片了,主要來講下第二步是怎麼實現的。
②我們在控制面板中使用生成異步操作。
首先,配置下服務引用,如下圖
然後我們在Reference上會看到生成如下幾個異步方法,也就是證明我們配置成功咯,接下來就開始擼代碼了。
/*按F12進入,我們可以看到如下代碼 public System.IAsyncResult BeginFly(string message, System.AsyncCallback callback, object asyncState) { return base.Channel.BeginFly(message, callback, asyncState); } 我們來分析下傳的形參 message:傳給接口的參數 callback:回調函數 asyncState:狀態 */ flyClient.BeginFly("hello World", new AsyncCallback((obj) => { var myClient = (FlyServiceClient)obj.AsyncState; string res = myClient.EndFly(obj); Console.WriteLine("調用結束:{0}", res); }), flyClient);
三.WCF的無配置
1. 我們在開啓ServiceHost的時候,啓用了一些配置文件.
也就是說這些config信息最終會被C#代碼讀取,然後C#代碼會動態的去讀取config,那何不我們自己去寫呢??
這樣的話,我們就可以最小化配置.
2.首先我們可以在ServiceHost上面開啓一個監聽器,用我們自己的代碼來實現配置文件。
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.ServiceModel.Description; using System.Text; using System.Threading.Tasks; namespace WcfServiceLHost { class Program { static void Main(string[] args) { #region //// <host> //// <baseAddresses> //// <add baseAddress="http://localhost:8733/MyService" /> //// </baseAddresses> ////</host> //ServiceHost host = new ServiceHost(typeof(Service1), new Uri("http://localhost:8733/MyService/")); ////這是我們服務的地址 //// <endpoint address="" binding="basicHttpBinding" contract="WcfServiceConfig.IFlyService"> //// <identity> //// <dns value="localhost" /> //// </identity> ////</endpoint> //host.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), string.Empty); ////mex元數據的地址 //// <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> //host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); ////host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); //// <behaviors> //// <serviceBehaviors> //// <behavior name=""> //// <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> //// <serviceDebug includeExceptionDetailInFaults="false" /> //// </behavior> //// </serviceBehaviors> ////</behaviors> ////host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true, HttpsGetEnabled = true }); ////var single = host.Description.Behaviors.Find<ServiceDebugBehavior>(); ////single.IncludeExceptionDetailInFaults = false; //host.Open(); //Console.WriteLine("WCF開啓!"); //Console.ReadKey(); #endregion //// <host> //// <baseAddresses> //// <add baseAddress="http://localhost:8733/MyService" /> //// </baseAddresses> ////</host> ServiceHost host = new ServiceHost(typeof(Service1), new Uri("http://localhost:8733/MyService/")); //// <endpoint address="" binding="basicHttpBinding" contract="WcfServiceConfig.IFlyService"> //// <identity> //// <dns value="localhost" /> //// </identity> ////</endpoint> //這是我們服務的地址 host.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), string.Empty); //// <behaviors> //// <serviceBehaviors> //// <behavior name=""> //// <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> //// <serviceDebug includeExceptionDetailInFaults="false" /> //// </behavior> //// </serviceBehaviors> ////</behaviors> //mex元數據的地址 host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true }); //<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> //mex元數據的地址 host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); host.Open(); Console.WriteLine("WCF 服務開啓"); Console.Read(); } } }