第一讲:WCF介绍
链接:https://pan.baidu.com/s/15Al0OwVpjMX8TRbOFB7qZg 提取码:o835

软件架构的设计经历了 从面向对象程序,到面向组件程序设计,再到面向服务程序设计。
这3种方式都致力于同一个目标:封装和重用。
1.面向对象程序设计:类封装功能并提供代码重用。
2.面向组件程序设计:用以共享封装了可重用类的二进制文档。最初,这一点只是针对本机,随着COM,DCOM,和.NET Remoting的问世,才发展到分布式环境。虽然这些分布式的方法不尽相同,但是都可以实现跨进程、跨机器。 面向组件程序设计有很多局限性,但是最明显的局限是与一些特定技术的耦合过深。JAVA客户端如何调用COM组件,.NET如何调用EJB,这些局限的产生均是协议和通信格式的问题。( 解释 技术的耦合过深: 例如我们的客户端是个Net技术开发的程序,服务端是一个EJB的技术,那么就不能进行通信的。 再例如,我们的客户端是一个Java技术开发的程序,那么就无法与服务端的COM组件进行通信。 这些都是因为相互之间的协议以及通信方式的不同所导致的)
3.面向服务程序设计:解决了不同客户之间的通信,也就是不必担心彼此采用了不同的技术。(面向服务程序设计解决了面向组件的弊端,不管是什么样的客户端都可以去访问服务端的程序 )
例如下图 [ 1-01 ]
不同的客户端以及应用程序都可以访问服务端A,B,C。
当然还有其它的理解,可以通过上网去查一些资料。





宿(Service Hosting)
1.自我寄宿(self-Hosting)
2.IIS寄宿(寄宿进程为IIS的工作进程W3wp.exe)
我们来看一个Demo ,在这个例子中,我们将实现一个简单的计算服务。客户端和服务通过运行在同一台机器上不同进程模拟。(和传统的分布式通信框架一样,WCF本质上提供一个跨进程、跨机器以致网路的服务调用)
这个例子可以看到 寄宿的 第一种情况 自我寄宿
第一步
先看构建的整个解决方案(说了这是只是先去看不去搭建):
1: Contracts:一个类库项目,定义服务契约(Service Contract)
2: Services:一个类库项目,提供对WCF服务的实现
3: Hosting:一个控制台应用,实现对定义在 Services项目中的服务的寄宿
4: Client:一个控制台应用模拟服务的客户端
通过VS创建一个空白的解决方案,添加4个项目。项目的类型,承载的功能和相互引用的关系如下,整个项目的结构如下:
1:Contracts:一个类库项目,定义服务契约(Service Contract), 引用System.ServiceMode程序集(WCF框架的绝大部分实现和API定义在该程序集中)
2:Services:一个类库项目,提供对WCF服务的实现。定义在该项目中的所有WCF服务实现了定义在Contracts中相应的服务契约,所以Services具有对Contracts项目的引用。
3:Hosting:一个控制台应用,实现对定义在Services项目中的服务的寄宿,该项目需要同时应用Contracts和Services两个项目和System.ServiceMode程序集。
4:Client:一个控制台应用模拟服务的客户端,该项目引用System.ServiceMode程序集。
[ 1-07 ]
第二步
从功能上讲,服务契约抽象了服务提供的所有操作,而站在消息交换的角度来看,服务契约则定义了基于服务调用的消息交换过程
一般地,我们通过接口的形式定义服务契约。WCF广泛采用基于自定义特性的声明编程模式,我们通过在接口上应用System.ServiceModel.ServiceContractAttribute特性将一个接口定义成服务契约。在应用ServiceContractAttribute特性的同时,还可以指定服务契约的名称和命名空间。通过应用ServiceContractAttribute特性将接口定义成服务契约之后,接口的方法成员并不能自动成为服务的操作。在此方面,WCF采用的是显示选择的策略:我们须要在相应的操作方法上面显示地应用OperationContractAttribute特性。
(上面的两句话什么意思呢?我们这里看一遍理解个大概不去深究,将整个Demo看完之后回来再看一遍上面的两句话就理解了,也不去管服务契约(契约 分 服务契约、数据契约、消息契约、错误契约),因为后面我们会说到,这里就把契约它看成程序中定义的接口就成了)
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks; namespace Contracts
{ [ServiceContract]
public interface ICalculator
{
[OperationContract]
double Add(double x, double y);
}
}
第三步
创建服务 Services
当服务契约创建成功时,我们需要通过实现服务契约来创建具体的WCF服务。WCF服务CalculatorService定义在Services项目中,实现了服务契约接口ICalculator,实现了所有的服务操作.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Contracts; namespace Services
{
public class CalculatorService : ICalculator
{
public double Add(double x, double y)
{
return x + y;
}
}
}
WCF服务需要依存一个运行着的进程(宿主),服务寄宿就是为服务指定一个宿主的过程。WCF是一个基于消息的通信框架,采用基于终结点(Endpoint)的通信手段。
1:地址(Address):地址决定了服务的位置,服务寻址的问题。
2:绑定(Binding):实现了通信的所有的细节,包括网络传输,消息编码等。
3:契约(Contract):契约是对服务操作的抽象,也是对消息交换模式以及消息结构的定义。
Endpoint=ABC ( Address 、Binding、Contract) 后面说的 EndPoint 就是指配置 A,B,C
服务寄宿的目的就是开启一个进程,为WCF服务提供一个运行的环境
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
using Contracts;
using Services; namespace Hosting
{
class Program
{
static void Main(string[] args)
{
//首先提供一个主机进程,实际上就是完成寄宿的主机( CalculatorService 完成了对契约的实现,所以我们这里就寄宿就寄宿它了 )
using (var host = new ServiceHost(typeof(CalculatorService)))
{
/*
然后 当我们把寄宿后,就要完成我们的EndPoint(终结点) 了,之前提过EndPoint=A,B,C 那么这里就要绑定了
之前的图片 [ 1-05 ] 已经展示 过这个 EndPoint
这里的 WSHttpBinding 就是 指定 HTTP 协议 当然还有很多种,后面说到
添加终结点 首先 C,然后 B 最后 A
*/
host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:6666/calculatorservice"); //这里检测 元数据 为不为空 这里的元数据也不管是什么东西,下面我们说到
if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
{
//也就是说这里我们是以元数据的形式发布出去进行客户端与服务器的交互
//控制服务元数据和相关信息的发布
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
behavior.HttpGetEnabled = true;//是否可以通过 HTTP Get 形式 去访问
// 元数据的地址,可以通过这个地址 在 浏览器中 进行访问
behavior.HttpGetUrl = new Uri("http://127.0.0.1:6666/calculatorservice/metadata");
//添加到元数据中去
host.Description.Behaviors.Add(behavior);
}
//指定一个事件,当服务启动之后 需要做什么,这里指定一个委托,在 Open 成功后,就执行这里的事件
host.Opened += (sender, eventArgs) => Console.WriteLine("服务已经启动,按任何按钮停止");
//开启服务
host.Open();
Console.Read();
}
}
}
}
到这里 我们服务器 部分 就完成了
接下来我们调试一下:
[ 1-08 ]
图片上传不成功,博客园不允许上传10M以上的图片。这么多年,博客园都没有好好更新下,我觉得挺让人窝火的。
好,非常成功。
我们直接在 浏览器中去访问: http://127.0.0.1:6666/calculatorservice/metadata
呈现出来的
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:tns="http://tempuri.org/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://tempuri.org/" name="CalculatorService">
<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:RequireDerivedKeys/>
<sp:BootstrapPolicy>
<wsp:Policy>
<sp:SignedParts>
<sp:Body/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/>
</sp:SignedParts>
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
<sp:SymmetricBinding>
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:SpnegoContextToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:RequireDerivedKeys/>
</wsp:Policy>
</sp:SpnegoContextToken>
</wsp:Policy>
</sp:ProtectionToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:EncryptSignature/>
<sp:OnlySignEntireHeadersAndBody/>
</wsp:Policy>
</sp:SymmetricBinding>
<sp:Wss11>
<wsp:Policy/>
</sp:Wss11>
<sp:Trust10>
<wsp:Policy>
<sp:MustSupportIssuedTokens/>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
</wsp:Policy>
</sp:Trust10>
</wsp:Policy>
</sp:BootstrapPolicy>
</wsp:Policy>
</sp:SecureConversationToken>
</wsp:Policy>
</sp:ProtectionToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:EncryptSignature/>
<sp:OnlySignEntireHeadersAndBody/>
</wsp:Policy>
</sp:SymmetricBinding>
<sp:Wss11 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy/>
</sp:Wss11>
<sp:Trust10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:MustSupportIssuedTokens/>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
</wsp:Policy>
</sp:Trust10>
<wsaw:UsingAddressing/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Add_Input_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<sp:Body/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/>
</sp:SignedParts>
<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<sp:Body/>
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="WSHttpBinding_ICalculator_Add_output_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<sp:Body/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="To"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="From"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="FaultTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="ReplyTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="MessageID"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="RelatesTo"/>
<sp:Header Namespace="http://www.w3.org/2005/08/addressing" Name="Action"/>
</sp:SignedParts>
<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<sp:Body/>
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsdl:types>
<xsd:schema targetNamespace="http://tempuri.org/Imports">
<xsd:import namespace="http://tempuri.org/" schemaLocation="http://127.0.0.1:6666/calculatorservice/metadata?xsd=xsd0"/>
<xsd:import namespace="http://schemas.microsoft.com/2003/10/Serialization/" schemaLocation="http://127.0.0.1:6666/calculatorservice/metadata?xsd=xsd1"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="ICalculator_Add_InputMessage">
<wsdl:part name="parameters" element="tns:Add"/>
</wsdl:message>
<wsdl:message name="ICalculator_Add_OutputMessage">
<wsdl:part name="parameters" element="tns:AddResponse"/>
</wsdl:message>
<wsdl:portType name="ICalculator">
<wsdl:operation name="Add">
<wsdl:input message="tns:ICalculator_Add_InputMessage" wsaw:Action="http://tempuri.org/ICalculator/Add"/>
<wsdl:output message="tns:ICalculator_Add_OutputMessage" wsaw:Action="http://tempuri.org/ICalculator/AddResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="WSHttpBinding_ICalculator" type="tns:ICalculator">
<wsp:PolicyReference URI="#WSHttpBinding_ICalculator_policy"/>
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Add">
<soap12:operation style="document" soapAction="http://tempuri.org/ICalculator/Add"/>
<wsdl:input>
<wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Add_Input_policy"/>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference URI="#WSHttpBinding_ICalculator_Add_output_policy"/>
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="CalculatorService">
<wsdl:port name="WSHttpBinding_ICalculator" binding="tns:WSHttpBinding_ICalculator">
<soap12:address location="http://127.0.0.1:6666/calculatorservice"/>
<wsa10:EndpointReference>
<wsa10:Address>http://127.0.0.1:6666/calculatorservice</wsa10:Address>
<Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
<Upn>DESKTOP-K3KFPAM\xujunheng</Upn>
</Identity>
</wsa10:EndpointReference>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
其实就是 WSDL 元数据
第一讲:WCF介绍的更多相关文章
- 第三讲:WCF介绍(3)
代码 https://yunpan.cn/cPns5DkGnRGNs 密码:3913 前面我们通过一个小的例子,大概了解的WCF. 这里我们补充下 EndPoint 配置 A,B,C 中 ...
- 32位汇编第一讲x86和8086的区别,以及OllyDbg调试器的使用
32位汇编第一讲x86和8086的区别,以及OllyDbg调试器的使用 一丶32位(x86也称为80386)与8086(16位)汇编的区别 1.寄存器的改变 AX 变为 EAX 可以这样想,16位通 ...
- 异常处理第一讲(SEH),筛选器异常,以及__asm的扩展,寄存器注入简介
异常处理第一讲(SSH),筛选器异常,以及__asm的扩展 博客园IBinary原创 博客连接:http://www.cnblogs.com/iBinary/ 转载请注明出处,谢谢 一丶__Asm的 ...
- 常见注入手法第一讲EIP寄存器注入
常见注入手法第一讲EIP寄存器注入 博客园IBinary原创 博客连接:http://www.cnblogs.com/iBinary/ 转载请注明出处,谢谢 鉴于注入手法太多,所以这里自己整理一下, ...
- 逆向实用干货分享,Hook技术第一讲,之Hook Windows API
逆向实用干货分享,Hook技术第一讲,之Hook Windows API 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) ...
- PE文件格式详解,第一讲,DOS头文件格式
PE文件格式详解,第一讲,DOS头文件格式 今天讲解PE文件格式的DOS头文件格式 首先我们要理解,什么是文件格式,我们常说的EXE可执行程序,就是一个文件格式,那么我们要了解它里面到底存了什么内容 ...
- 机器学习基石第一讲:the learning problem
博客已经迁移至Marcovaldo's blog (http://marcovaldong.github.io/) Andrew Ng的Machine Learning比較简单,已经看完.林田轩的机器 ...
- Stanford概率图模型: 第一讲 有向图-贝叶斯网络
原文链接(系列):http://blog.csdn.net/yangliuy/article/details/8067261 概率图模型(Probabilistic Graphical Model)系 ...
- 第一讲,DOS头文件格式
今天讲解PE文件格式的DOS头文件格式 首先我们要理解,什么是文件格式,我们常说的EXE可执行程序,就是一个文件格式,那么我们要了解它里面到底存了什么内容 简短的说明. 我们要知道,PE文件格式,是微 ...
- 干货|漫画算法:LRU从实现到应用层层剖析(第一讲)
今天为大家分享很出名的LRU算法,第一讲共包括4节. LRU概述 LRU使用 LRU实现 Redis近LRU概述 第一部分:LRU概述 LRU是Least Recently Used的缩写,译为最近最 ...
随机推荐
- JavaBean和Map转换封装类
package com.ljq.util; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans. ...
- (转)Hibernate事务管理
Hibernate的事务管理 事务(Transaction)是工作中的基本逻辑单位,可以用于确保数据库能够被正确修改,避免数据只修改了一部分而导致数据不完整,或者在修改时受到用户干扰.作为一名软件设计 ...
- Java关于流知识总结
流总结: 一.流的分类: 数据单位:字节流 字符流 方向: 输出流 输入流 角色: 节点流 套节流 字节流:以Stream结尾. 字符流:以Reader 和Writer 结尾. 输入流:所有带有 ...
- WebApi系列~开放的CORS,跨域资源访问对所有人开放
回到目录 之前有客户问我,如何AJAX跨域post,这个问题挺有意思,在我们看来,我是不被允许的,因为它是不安全的,但随着web api的火热,这个东西也被人们一步步的接受了,确实,有时,我们的接口希 ...
- atitit 业务 触发器原理. 与事件原理 docx
atitit 业务 触发器原理. 与事件原理 docx 1.1. 呵呵,你需要需要一个业务 触发器..1 1.2. 触发器/事件/中断的原理1 1.3. Io 硬件中断的原理( 中断的低层有cpu轮询 ...
- Java六大问题你都懂了吗?
这些问题对于认真学习java的人都要必知的,当然如果你只是初学者就没必要那么严格了,那如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初学者行列. 一.到底要怎么样初始化! 本问题讨论 ...
- hibernate(八) Hibernate检索策略(类级别,关联级别,批量检索)详解
序言 很多看起来很难的东西其实并不难,关键是看自己是否花费了时间和精力去看,如果一个东西你能看得懂,同样的,别人也能看得懂,体现不出和别人的差距,所以当你觉得自己看了很多书或者学了很多东西的时候,你要 ...
- 解决h5的video标签,android、ipad客户端播放正常,iphone客户端无法播放
在做html5时插入一个视频播放标签video后,测试时android.ipad客户端播放正常,唯独iphone自带浏览器无法播放. 解决办法: 判断用户所使用客户端访问h5页面时是iphone时,点 ...
- SQL Server的小数数值类型(float 和 decimal)用法
在SQL Server中,小数数值实际上只有两种数据类型:float 和 decimal.double precision 整体是数据类型,等价于 float(53),real等价于float(24) ...
- 利用border属性制作各种图形。
这是一个比较正常的 但如果我们把宽度和高度去掉呢? 好像看不太出来对吧,我们来给边框加上不同颜色. 看出啥了没,分明就是每个边都是一个三角形啊. 那假如我想要一个朝下的三角形是不是我只要把border ...