WCF
一、WCF的基础概念
WCF的几个重要基础概念如下:
1.地址
地址指定了接受消息的位置,WCF中的地址以统一资源标识符(URL)的形式定义。URL由通信协议和位置两部分组成。如http://localhost:8000/ 表明通信协议为http,位置是localhost(本机)的8000端口.
WCF中支持的传输协议包括HTTP、TCP、IPC(基于命名管道的内部进程通信)、MSMQ(微软消息队列)以及Peer network(对等网),它们对应的地址类型如下:
HTTP地址:使用HTTP协议进行传输,其地址形式为:http://localhost:8000/
TCP地址:使用TCP协议进行传输,其地址形式为:net.tcp://localhost:8000/
IPC地址:使用net.pipe进行传输,其地址形式为:net.pipe://localhost/
MSMQ地址:使用Micorsoft Message Queue机制进行传输,其定制形式为net.msmq://localhost/
对等网地址:使用net.p2p进行传输,其地址形式为net.p2p://localhost
2.绑定(Binding)
由于WCF支持HTTP、TCP、Named Pipe、MSMQ、Peer-To-Peer TCP 等协议,HTTP又分为基本HTTP支持(BasicHttpBinding)以及WS-HTTP支持(WsHttpBinding),而TCP又支持NetTcpBinding,
NetPeerTcpBing等通信方式,因此双方必须要统一通信的协议,并且要在编码以及格式上保持一致。
WCF的服务可以挂载于Console Application、WindowsApplication、IIS(ASP.Net) Application、Windows Wervice以及Windows Activation Services中,但大多数都会挂在Windows Service。
主要的系统内置绑定如下:
3.契约(Contract)
WCF的基本概念是以契约(Contract)来沟通双方的协议,契约必须以接口的方式来体现,而实际的服务代码必须要由这些契约接口派生实现。契约可分为以下四种:
服务契约(ServiceContract):指定服务的定义
数据契约(DataContract):指定双方沟通时的数据格式
操作契约(DataContract):指定服务提供的方法
消息契约(MessageContract):指定在通信期间改写消息内容的规范
一个WCF的契约如图下列代码所示:
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")] public interface ICalculator { [OperationContract] double Add(double n1, double n2); [OperationContract] double Subtract(double n1, double n2); [OperationContract] double Multiply(double n1, double n2); [OperationContract] double Divide(double n1, double n2); }
4.终结点
5.元数据
所谓“元数据”就是描述数据的数据,即描述当前服务有哪些服务契约,方法契约和数据契约以及终结点信息。当客户端添加WCF服务引用的时候会首先通过元数据取得服务端的契约信息,
终结点信息,然后通过这些信息在客户端创建代理类。
6.宿主
一种应用程序或者进程,服务将在该环节下运行。
二、创建一个WCF程序
1.新建一个空解决方案WCFService,选择“新建项目->类库”,这里不直接创建WCF服务,而是创建一个类库,命名为MyService
2.添加System.ServiceModel程序集引用
3.新建一个接口ICalculator,引入System.ServiceModel命名空间
[ServiceContract] public interface ICalculator { [OperationContract] double Add(double n1, double n2); [OperationContract] double Subtract(double n1, double n2); [OperationContract] double Multiply(double n1, double n2); [OperationContract] double Divide(double n1, double n2); }
4.添加Calculator类实现ICalculator接口:
public class Calculator : ICalculator { public double Add(double n1, double n2) { return n1 + n2; } public double Divide(double n1, double n2) { return n1 / n2; } public double Multiply(double n1, double n2) { return n1 * n2; } public double Subtract(double n1, double n2) { return n1 - n2; } }
5.新建宿主,选择“新建项目->控制台应用程序”,并命名为MyServiceHost
6.添加System.ServiceModel引用和项目引用MyService
7.新建一个MyHost类用来创建ServiceHost对象
public class MyHost : IDisposable { /// <summary> /// 定义一个服务宿主对象 /// </summary> private ServiceHost _myHost; public const string BaseAddress = "net.pipe://localhost";//基地址 public const string CalculatorServiceAddress = "Calculator";//可选地址 public static readonly Type ServiceType = typeof(MyService.Calculator);//服务契约实现类型 public static readonly Type ContractType = typeof(MyService.ICalculator);//服务契约接口类型 public static readonly Binding MyBinding = new NetNamedPipeBinding();//定义一个绑定 public MyHost() { CreateMyServiceHost(); } /// <summary> /// 创建服务宿主对象 /// </summary> protected void CreateMyServiceHost() { _myHost = new ServiceHost(ServiceType, new Uri[] { new Uri(BaseAddress) });//创建服务对象 _myHost.AddServiceEndpoint(ContractType, MyBinding, CalculatorServiceAddress);//添加终结点 } /// <summary> /// 开启服务 /// </summary> public void Open() { Console.WriteLine("开始启动服务..."); _myHost.Open(); Console.WriteLine("服务已经启动..."); } /// <summary> /// 销毁服务宿主对象 /// </summary> public void Dispose() { if(_myHost != null) { (_myHost as IDisposable).Dispose(); } } }
在Main函数中调用:
class Program { static void Main(string[] args) { using (MyHost host = new MyHost()) { host.Open(); Console.ReadKey(); } } }
8.创建客户端调用程序,选择“新建项目->控制台应用程序”,并命名为MyClient,添加MyService引用
9.添加CalculatorProxy代理类
public class CalculatorProxy: ClientBase<ICalculator>,ICalculator { public static readonly Binding MyBinding = new NetNamedPipeBinding();//定义一个绑定 //主要这里要和服务宿主里定义的地址保持一致 public static readonly EndpointAddress CalculatorAddress = new EndpointAddress(new Uri("net.pipe://localhost/Calculator"));//地址 public CalculatorProxy():base(MyBinding, CalculatorAddress) { } public double Add(double n1, double n2) { return Channel.Add(n1,n2); } public double Subtract(double n1, double n2) { return Channel.Subtract(n1, n2); } public double Multiply(double n1, double n2) { return Channel.Multiply(n1, n2); } public double Divide(double n1, double n2) { return Channel.Divide(n1, n2); } }
在Main方法中调用:
class Program { static void Main(string[] args) { using (CalculatorProxy proxy = new CalculatorProxy()) { Console.WriteLine("10+5={0}",proxy.Add(10,5)); Console.WriteLine("10-5={0}", proxy.Subtract(10, 5)); Console.WriteLine("10*5={0}", proxy.Multiply(10, 5)); Console.WriteLine("10/5={0}", proxy.Divide(10, 5)); } Console.ReadKey(); } }
10.运行MyServiceHost.exe,如下图:
11.运行MyClient.exe,如下图: