1.什么是WCF

  Windows Communication Foundation(WCF)是一个面向服务(SOA)的通讯框架,作为.NET Framework 3.0的重要组成部分于2006年正式发布。WCF的使命是对Windows平台下现有的通讯技术(包括:COMDCOM.NET RemotingWeb ServicesMSMQWinSocket)进行全面整合,并设计了一个统一的程序开发模型(API),对于数据通信提供了最基本最有弹性的支持。

2.WCF的体系结构

  我们从下面WCF的体系结构图可以看出WCF是Windows平台下通讯技术的集大成者:

  

3.WCF的寄宿

  首先WCF应用程序是不能独立存在的,它必须依附于(寄宿)于其他的应用程序(宿主)中,宿主进程是专为承载服务而设计的应用程序。这些宿主进程包括 Internet 信息服务 (IIS)、Windows 激活服务 (WAS) 和 Windows 服务、开发人员创建的应用程序。

4.WCF的HelloWorld

  说千遍不如做一遍,下面我们通过一个简单的示例程序来学习如何构建一个WCF程序,以便于对WCF编程建立一个初步的印象。我们创建一个计算器服务,实现简单的加、减、乘、除的操作,然后由另一个进程(本地或远程)来调用这个服务。

4.1,创建HelloWcfService解决方案。 (切记已管理员身份运行VS,否则会报错的)

  首先我们创建一个名为:HelloWcfService解决方案,在该解决方案下创建一个Hosting的控制台项目;用于承载WCF服务。接着创建一个ContractService类库项目,定于定于服务的契约(接口);再最后创建一个Service类库项目,用于实现ContractService定义的服务契约(接口)。如下:

  

4.2,定义服务的契约(接口)

  从字面上来理解,服务契约就是:服务所提供操作的一个抽象。服务契约指定了服务支持的操作,通过使用接口来创建契约,接口中的每个方法都应对与特定的服务操作,同时定义契约的接口必须应用ServiceContractAttribute特性,同时我们需要在接口中定义的方法应用OperationContractAttribute特性,否则不公开该方法。

  我们在创建的解决方案中的ContractService类库项目中引用System.ServiceModel程序集,并添加System.ServiceModel命名空间,接着创建一个用于定义服务契约的接口,代码如下:

 1 using System.ServiceModel;
2
3 namespace ContractService
4 {
5 [ServiceContract(Name = "CalculatorService", Namespace = "http://www.cnblogs.com/IPrograming")]
6 public interface ICalculator
7 {
8 [OperationContract]
9 double Add(double num1, double num2);//加法
10 [OperationContract]
11 double Subtract(double num1, double num2);//减法
12 [OperationContract]
13 double Multiply(double num1, double num2);//乘法
14 [OperationContract]
15 double Divide(double num1, double num2);//除法
16 }
17 }

4.3,实现服务契约(接口)

  在前面我们只是对服务具有哪些操作进行一个抽象的定义,我们需要这个抽象的契约进行实现。在我们的这个例子中就是实现ICalculator接口。首先我们在Service的类库项目添加对ContractService类库项目的引用,并添加ContractService命名空间,然后实现ICalcultor接口,代码如下:

 1 using System;
2 using ContractService;
3
4 namespace Service
5 {
6 public class CalculatorService : ICalculator
7 {
8 #region ICalculator 成员
9
10 /// <summary>加法</summary>
11 public double Add(double num1, double num2)
12 {
13 return num1 + num2;
14 }
15
16 /// <summary>减法</summary>
17 public double Subtract(double num1, double num2)
18 {
19 return num1 - num2;
20 }
21
22 /// <summary>乘法</summary>
23 public double Multiply(double num1, double num2)
24 {
25 return num1 * num2;
26 }
27
28 /// <summary>除法</summary>
29 public double Divide(double num1, double num2)
30 {
31 return num1 / num2;
32 }
33
34 #endregion
35 }
36 }

4.4,承载(寄宿)和运行服务

  通过前面我们知道WCF服务是无法独立存在在,它必须是寄宿于其他的宿主(应用程序)中,寄宿服务的对象可以是开发人员自己创建的应用程序可以使用IIS和Windows服务等作为服务的宿主。在这里我们通过创建的控制台程序来作为服务的宿主。

  在编写借宿WCF服务的代码前我们需要先了解几个概念:

终结点:

WCF服务的所有通信是通过该服务的终结点进行的。 利用终结点,客户端可访问 WCF 服务提供的功能。终结点由三部分组成:

  • 地址:地址唯一地标识终结点,并告诉服务的潜在客户其所在的位置。
  • 绑定:指定如何与终结点进行通信(包括使用的通信协议和消息编码等)。
  • 契约:契约抽象了服务的操作,公开了终结点向客户端开放的功能。

 

元数据:

WCF 服务使用元数据来描述如何与服务终结点进行交互,以便工具(例如:Svcutil.exe)生成用于访问服务的客户端代码。

  在解决方案的Hosting项目中添加对System.ServiceModel程序集Service项目以及ContractService类库项目的引用,并添加相应的命名空间。代码如下:

 1   static void Main(string[] args)
2 {
3 //定义承载服务的类型和承载服务的基址
4 using (ServiceHost host = new ServiceHost(typeof(CalculatorService), new Uri("http://localhost:8889/CalculatorService")))
5 {
6 //增加一个服务终结点
7 host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
8
9 //使用元数据
10 ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
11 //使用HTTP/GET请求
12 behavior.HttpGetEnabled = true;
13 //定义元数据发布地址
14 behavior.HttpGetUrl = new Uri("http://localhost:8889/CalculatorService/Metadata");
15 //将元数据的定义添加到承载服务中
16 host.Description.Behaviors.Add(behavior);
17
18 // 启动服务
19 host.Open();
20 Console.WriteLine("CalculatorService服务运行中...\n");
21 Console.WriteLine("按任意键退出.");
22 Console.Read();
23 // 关闭服务
24 host.Close();
25 }
26 }

运行宿主程序后,我们在浏览器中输入下面的地址进行查看服务是否成功运行:

  • 服务的地址:http://localhost:8889/CalculatorService 
  • 元数据的地址:http://localhost:8889/CalculatorService/Metadata

5.调用WCF服务

  前面我们已经成功的创建一个可以用于基础运算的WCF服务,我们创建一个HelloWcfClient控制台应用程序用来调用前面WCF提供的服务,我们通过这个服务发布的元数据来生成调用代码(使用Svcutil.exe工具)Visual Studio可以为我们简化这一过程:运行WCF服务的宿主程序后,为HelloWcfClient项目添加服务引用,服务的地址就是前面创建的元数据地址:http://localhost:8889/CalculatorService/Metadata ,Visual Studio会自动生成一系统服务调用的代码和配置(这里暂时不做讨论)。

  只需要几行代码就可以完成服务的调用,调用代码如下:

 1         static void Main(string[] args)
2 {
3 using (CalculatorServiceClient proxy = new CalculatorServiceClient())
4 {
5 Console.WriteLine("{0}+{1}={2}", 1, 2, proxy.Add(1, 2));
6 Console.WriteLine("{0}-{1}={2}", 5, 2, proxy.Subtract(5, 2));
7 Console.WriteLine("{0}*{1}={2}", 1, 2, proxy.Multiply(1, 2));
8 Console.WriteLine("{0}/{1}={2}", 1, 2, proxy.Divide(1, 2));
9 }
10 Console.Read();
11 }

运行结果如下:

猛击下载:示例程序

参考资料&进一步阅读

Windows Communication Foundation

Windows Communication Foundation 体系结构

元数据

终结点

ServiceModel 元数据实用工具

《WCF全面解析》

WCF学习笔记(1)——Hello WCF的更多相关文章

  1. [WCF学习笔记] 我的WCF之旅(1):创建一个简单的WCF程序

    近日学习WCF,找了很多资料,终于找到了Artech这个不错的系列.希望能从中有所收获. 本文用于记录在学习和实践WCF过程中遇到的各种基础问题以及解决方法,以供日后回顾翻阅.可能这些问题都很基础,可 ...

  2. WCF学习笔记之事务编程

    WCF学习笔记之事务编程 一:WCF事务设置 事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元: WCF通过System.ServiceModel.TransactionFlowA ...

  3. WCF学习笔记之传输安全

    WCF学习笔记之传输安全 最近学习[WCF全面解析]下册的知识,针对传输安全的内容做一个简单的记录,这边只是简单的记录一些要点:本文的内容均来自[WCF全面解析]下册: WCF的传输安全主要涉及认证. ...

  4. WCF 学习笔记之异常处理

    WCF 学习笔记之异常处理 1:WCF异常在配置文件 <configuration> <system.serviceModel> <behaviors> <s ...

  5. WCF 学习笔记之双工实现

    WCF 学习笔记之双工实现 其中 Client 和Service为控制台程序 Service.Interface为类库 首先了解契约Interface两个接口 using System.Service ...

  6. WCF学习笔记(2)——使用IIS承载WCF服务

    通过前面的笔记我们知道WCF服务是不能独立存在,必须“寄宿”于其他的应用程序中,承载WCF服务的应用程序我们称之为“宿主”.WCF的多种可选宿主,其中比较常见的就是承载于IIS服务中,在这里我们来学习 ...

  7. 多线程编程学习笔记——异步调用WCF服务

    接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...

  8. WCF学习笔记

    1,关于WCF/web service/WSE Web Service:是行业标准,也就是Web Service 规范,也称作WS-*规范,既不是框架,也不是技术.它有一套完成的规范体系标准,而且在持 ...

  9. WCF学习笔记(二):简单调用

    转:http://www.cnblogs.com/wengyuli/archive/2009/11/08/1598428.html 一个通信会话过程有两个部分组成,客户端和服务端,他们要进行会话就必然 ...

随机推荐

  1. 关于java.lang.IllegalArgumentException: View not attached to window manager 错误的分析

    今天遇到一个很奇特的问题,当用户设置了PIN码,在锁屏界面正常解锁PIN码后,进入Launcher时显示com.android.phone 已停止运行.一开始猜想会不会是解锁PIN码的时候处理导致了P ...

  2. 免费LInux主机资源

    一.m-net.arbornet.org注冊 (1)telnet m-net.arbornet.org vista系统默认是关闭telnet的(由于不安全),须要开启.cmd->telnet(2 ...

  3. UIBezierPathStudyDemo

    import UIKit import XCPlayground //创建view let myView = UIView(frame:CGRectMake(0, 0, 300, 200)) //实时 ...

  4. 0c-35-自动释放池使用注意

    .autorelease使用注意 )并不是放到自动释放池中,都会自动加入到自动释放池 1.1) 因为没有调用autorelease方法,所以对象没有加入到自动释放池. int main(){ @aut ...

  5. mysql 线程级别的缓冲区

    线程栈信息使用内存(thread_stack) 主要用来存放每一个线程自身的标识信息,如线程id,线程运行时基本信息等等,我们可以通过 thread_stack 参数来设置为每一个线程栈分配多大的内存 ...

  6. js获得控件位置

    网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:document.body.offsetWid ...

  7. git的.gitignore配置

    .gitignore 配置文件用于配置不需要加入版本管理的文件,配置好该文件可以为我们的版本管理带来很大的便利,以下是个人对于配置 .gitignore 的一些心得. 1.配置语法: 以斜杠“/”开头 ...

  8. 浅析SQL Server 2005中的主动式通知机制

    一.引言 在开发多人同时访问的Web应用程序(其实不只这类程序)时,开发人员往往会在缓存策略的设计上狠下功夫.这是因为,如果将这种环境下不常变更的数据临时存放在应用程序服务器或是用户机器上的话,可以避 ...

  9. jquery . fancybox()

    1.父页面 function chooseTopic(btn) {//选择议题 $.fancybox({ type : 'iframe', href : '', fitToView : false, ...

  10. 1.4.1.Documents,Fields和Schema概述

    Documents,Fields和Schema概述 solr的基本前提是非常简单,你可以给它很多信息,然后可以向它提出问题,获取你想要的问题的信息.所有信息输入的地方就叫做索引或者更新.当你提出问题时 ...