WCF全称是Windows Communication Foundation,它是.NET3.0的重要组成部分,用来解决Windows下的一些通信方面的问题。WCF是Microsoft平台上的SOA架构,SOA即面向服务的架构(Service Oriented Architecture)。它的好处是提供了统一的编程模型,在这之前为了解决不同的需求可能要使用不同的技术比如:Web service\.NET Remoting\Enterprise Service等等,使用WCF就可以用单一的编程方式实现各种技术从而满足需求,也就是说程序员只要学习WCF一种技术就可以通过配置文件的方式实现不同技术的要求,可以把WCF看作是其他通信技术的封装和整合。

下图为WCF在.NET3.0框架中的位置:

上面基本的介绍了一下什么是WCF,但是要更好的理解它,我们还必须理解SOA这种架构。

SOA架构较比早期的3层架构多了一个服务层,它的好处如下所述。早期3层架构的业务逻辑层是直接暴露给表示层的,这就限定了客户层的技术受到业务逻辑层技术的限制,比如:业务逻辑层用的是COM,那么客户层就要使用COM相关技术来调用;第二当业务逻辑层比较复杂,对象较多时也会给客户层的调用带来不方便。SOA架构就解决了这些问题,WCF实际上就是用来做服务层的。它是用http Web Service的行业标准来通信的,所以不会受到技术限制,同时也更好的封装了业务逻辑层,只要服务不变,那么所有客户层的代码都不需要修改。对于SOA的部署方式其实还是有很多种,对于SOA部署的专题将在另一篇文章中专门讲解。

下面来讨论一下WCF的客户端和服务器之间是怎样交互的,我们结合下图来说明访问的原理。

首先是要有一个Service,这个Service想要运行必须有一个宿主主机ServiceHost,Service是安插在主机ServiceHost里面的,而且他们两个是在一个主机进程当中的。Endpoint是主机向外发布的访问服务的接口,也就是说如果外面有个客户端想要访问这个服务,就要通过Endpoint来访问。在客户端应用程序Clinet App中有一个Proxy,这个Proxy实际上就是由来实现客户端和服务端通信的,其实Proxy并不是直接与服务端的Endpoint直接通信,而是用proxy中的Endpoint和服务端的Endpoint通信。

下面看一个简单的Demo,体会一下WCF开发是怎么样的。为了能更好的理解上图的通信过程,下面的Demo是完全手工方式实现的WCF,没有创建现成的WCF项目,这样会更好的理解每一部分的结构。可能会用到下面的两条,即使下面的这个Demo用不到,在以后的WCF开发中也会用到,其中一个是配置文件工具,另一个是解决无法添加引用的问题,这里只是提一下,如果以后需要可以有个印象:

应用程序配置文件工具:svconfigeditor.exe
有用的一个命令:D:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe /resetskippkgs,当无法添加服务引用时使用,可以解决下图的问题。

首先我们创建一个C#的Windows Project的Class Library工程项目,这个项目作为WCF通信结构图中的的Service部分,叫做HelloWorldService,我们将在这个Service中添加和编写我们想要提供的服务。然后添加新的.NET dll引用System.ServiceModel,结构如下图。

Service.cs代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; namespace WCF.Demo
{
    [ServiceContract(Namespace="http://www.cnblogs.com/charlesliu")]
    public interface IService
    {
        [OperationContract]
        string HelloWorld(string message);
    }     public class HelloWorldService : IService
    {
        public string HelloWorld(string message)
        {
            return string.Format("At {0}, I will say {1}", DateTime.Now, message);
        }
    }
}

下面对这部分代码讲解一下,首先要using System.ServiceModel;这可以使得程序可以使用相应的Contract属性标签,如本例中的ServiceContract和OperationContract。WCF的程序是由一个Interface和一个实现了这个Interface的class组成,[ServiceContract(Namespace=“http://www.cnblogs.com/charlesliu”)]标记是用来标示对外的服务,[OperationContract]这个标记是用来标示此服务提供的具体功能。也就是说这个Service要完成哪些事情是通过接口来定义的,具体的用一个Class来实现它。这两个属性标签实际上就是客户端和服务端通信的一个契约,两边都必须满足,对于契约将在后续文章中提到。

接下来著作ServiceHost部分,添加一个Console Application类型的新工程,如下图:

在Host项目中添加System.ServiceMode引用和HelloWorldService的工程引用。

Host.cs的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; namespace WCF.Demo
{
    public class Host
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(WCF.Demo.HelloWorldService)))
            {
                host.AddServiceEndpoint(typeof(WCF.Demo.IService), new WSHttpBinding(), "http://localhost:9000/HelloWorld"); ;
                host.Open();
                Console.WriteLine("Host in started successful!");
                Console.Read();
            }
        }
    }
}

首先定义一个ServiceHost对象实例,其中的参数代表了实例将是以那种类型的Service启动运行,本例中使用WCF.Demo.HelloWorldService服务实现类为ServiceHost运行时类型。然后为ServiceHost实例添加Endpoint,其中三个参数代表:服务接口,通信方式,通信地址。然后打开服务并等待客户端的消息。

接下来制作Client部分,也是添加一个新的Console Application类型的工程,如下图:

添加System.ServiceModel引用。

Client.cs的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; namespace WCF.Demo
{
    [ServiceContract(Namespace = "http://www.cnblogs.com/charlesliu")]
    public interface IService
    {
        [OperationContract]
        string HelloWorld(string message);
    }     class Client
    {
        static void Main(string[] args)
        {
            IService proxy = ChannelFactory<IService>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:9000/HelloWorld"));
            string message = proxy.HelloWorld("Hello, World - Charles");
            Console.WriteLine(message);
            Console.ReadLine();
        }
    }
}

Client端的契约要和Service端的契约一致,也就是保证两端的访问契约一致(其实就是copy过来,一模一样的),然后定义Proxy用ChannelFactory类,通过泛型泛化到IService服务契约接口,传递参数通信方式,Endpoint和通信地址,然后调用服务的功能。

运行方法:

先启动Host程序:

  若遇到如下问题:

  HTTP 无法注册 URL [url]http://localhost:8086/[/url]。进程不具有此命名空间的访问权限
  解决办法:Visual Studio以管理员的身份运行就可以了。

此时主机的服务就起来了,他一直等待着Client的调用。然后运行Client程序,就会产生如图效果,Client得到响应,看到了Service处理的结果。

上面的例子很好的解释了WCF整个通信过程,其实在实践开发中没有这么麻烦,很多东西都是自动生成的,而且加上配置文件使得相关工作更加简单。通过上边的例子我们对原生态的WCF有了个很清晰的认识,为今后的学习打下了坚实的基础。下面总结一下上面的例子,可以得到如下:

服务器端:
定义和实现服务契约
为服务类型构建ServiceHost 实例,暴露endpoints
打开通讯通道
客户端:
需要服务契约的一个副本和关于endpoints的信息
为特定的endpoint构建通信通道并且调用操作

下图的ABC是Endporint通信的基本条件:

至此WCF的原理和概述就完成了,现在大家对WCF应该有了一个初步的认识,对于更加细节的知识会在后续文章中继续说明。(完)

WCF 之 概述的更多相关文章

  1. 【WCF--初入江湖】01 WCF编程概述

    01 WCF编程概述 SOA的优点 1.服务独立于平台和工作环境.服务并不关心自己所处的环境,也不关心与之进行通信的服务所处的    环境. 2.服务相互隔离. 3.服务对协议.格式和传输中立. 4. ...

  2. WCF初探-21:WCF终结点(endpoint)

    WCF终结点概述 在之前文章的示例中,我们都是通过配置服务的终结点(endpoint)发布的服务,供客户端调用,这是因为WCF服务的所有通信都是通过该服务的终结点进行的.每个终结点(endpoint) ...

  3. MSDN Webcast 跟我一起从零开始学WCF系列课程

    系列课程 >跟我一起从零开始学WCF系列课程   跟我一起从零开始学WCF系列课程(1):WCF概述 (Level 200)   讲 师:徐长龙    课程简介:从 本堂课开始我们将开启一个新的 ...

  4. WCF 之 生成元数据和代理

    在WCF开发概述中讲解了手工方式的WCF应用,其实实际开发中使用更多的使用配置方式和元数据来实现WCF,下面我们来看一个具体的Demo,这个例子和WCF开发概述中使用的是同一个例子,只是实现方式不同, ...

  5. wcf编程资料

    如下为WCF编辑资料 链接:https://pan.baidu.com/s/1kZnc6eNOfEggHSfJNXj8Ag 提取码:gj7s 复制这段内容后打开百度网盘手机App,操作更方便哦 第01 ...

  6. 【WCF--初入江湖】目录

    [WCF--初入江湖]目录 [WCF--初入江湖]01 WCF编程概述 [WCF--初入江湖]02 WCF契约 [WCF--初入江湖]03 配置服务 [WCF--初入江湖]04 WCF通信模式 [WC ...

  7. WCF学习之旅—WCF概述(四)

    一.WCF概述 1) 什么是WCF? Windows Communication Foundation (WCF) 是用于构建面向服务的应用程序的框架.借助 WCF,可以将数据作为异步消息从一个服务终 ...

  8. [WCF编程]12.事务:事务概述

    一.事务概述 维护系统一致性和正确地处理错误恢复挑战的最佳方式是使用事务. 一个事务就是一个复杂操作的集合,这个集合中任何一个操作的失败都会引起整个集合的失败. 尽管在事务进行时系统被允许暂时出于不一 ...

  9. [WCF编程]5.绑定概述

    一.绑定概述 WCF提供了一个编程框架,可以抽象化服务创建的复杂过程.绑定允许开发人员将精力集中在问题本身上,而无需考虑如何创建允许系统运行的架构,因为WCF已经创建了架构. 绑定类型是开发人员控制W ...

随机推荐

  1. AttributeError: 'ForeignKey' object has no attribute 're' 解决办法

    使用 field_object.rel.model.objects.filter(**db_condition) 报错 forekey中存在rel,为什么不能调用? 通过以下语句观察 print(fi ...

  2. 计蒜客 A2232.程序设计:蒜厂年会-单调队列(双端队列(STL deque)实现)滑窗维护最小前缀和

    程序设计:蒜厂年会 问答问题反馈 只看题面 16.79% 1000ms 262144K   在蒜厂年会上有一个抽奖,在一个环形的桌子上,有 nn 个纸团,每个纸团上写一个数字,表示你可以获得多少蒜币. ...

  3. 17-7-26-react-router入门

    完蛋了,上司最近都和颜悦色的,搞得我跑路的决心大大减退,不过还是要跑路.毕竟面向工资编程.今天一天基本都在挑项目的CSS,由于是别人哪里直接copy的,然后css我也直接copy的codepen上的源 ...

  4. go chapter 2 - read file(yaml)

    func main() { data, err := ioutil.ReadFile("D:/test/widua.go") if err != nil { fmt.Println ...

  5. JavaScript 对象创建

    tips: JavaScript 除了null和undefined之外,其他变量都可以当做对象使用. JavaScript 的基本数据类型有:number boolean string null  u ...

  6. POJ - 1835 宇航员(模拟题)

    问题描述: 宇航员在太空中迷失了方向,在他的起始位置现在建立一个虚拟xyz坐标系,称为绝对坐标系,宇航员正面的方向为x轴正方向,头顶方向为z轴正方向,则宇航员的初始状态如下图所示: 现对六个方向分别标 ...

  7. BZOJ 2296【POJ Challenge】随机种子(构造)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2296 [题目大意] 给出一个数x,求一个10的16次以内的数使得其被x整除并且数字包含 ...

  8. Java学习笔记(14)

    需求:一个银行账户5000块,两夫妻一个拿着存折,一个拿着卡,开始取钱比赛,每次只能取1000,要求不准出现线程安全问题 public class Demo10 { public static voi ...

  9. friend ---- public and private

    I mean the difference between: class A{public: friend class B;};and class A{private: //or nothing as ...

  10. mq组件介绍

    作者:Jaskey Lam链接:https://zhuanlan.zhihu.com/p/25069846来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. RocketM ...