代码

https://yunpan.cn/cPns5DkGnRGNs   密码:3913


前面我们通过一个小的例子,大概了解的WCF。
这里我们补充下  EndPoint 配置  A,B,C  中的  A ( Address ),  格式 是:  [传输协议]://[主机名称|域名|IP地址]:[可选端口号]/[资源路径]   就是  URI(统一资源标识) ,它唯一标识一个确定的网络资源,同时也表示资源所处的位置及访问的方式(资源访问所用的网络协议)。

典型传输协议下的URI

(1)HTTP和HTTPS

HTTPS(安全超文本传输协议).它是为了在WWW上解决安全的数据传输

而设计的。HTTS是采用了SSL的HTTP,SSL是一种加密协议。它们默认的端口

号分别是80和443

http://127.0.0.1:80/calculatorService

https://127.0.0.1:443/calculatorService

这里的端口好必须写,如果不写 的话 是默认的,而  配置  EndPoint 的 A  为 http和https  默认的端口号的时候会 报错,因为端口号 被占用了,所以这里注意 ,一定要把端口号写上  

(2)TCP

WCF通过NetTcpBinding支持基于TCP的传输。对于TCP的URI,其传输协议前缀均为

net.tcp://。默认端口号808

net.tcp://127.0.0.1:808/calculatorService

(3):Pipe

对于同一台机器上不同进程间的通信(IPC),WCF具有专门的实现方式:命名管道(Named Pipes).

通过命名管道进行跨进程通信能够获得最好的性能优势。WCF将命名管道专门用于同一台机器的跨

进程通信,所以基于IPC的URI的主机名|域名|IP地址部分只能是本机的机器名,或者直接是localhost

或127.0.0.1

基于IPC的URI, 都具有net.pipe前缀,端口没有任何意义.

net.pipe://127.0.0.1/calculatorService

(4):Msmq  消息队列

net.msmq://xxx.com/calculatorService (公有队列)

net.msmq://xxx.com/private/calculatorService(私有队列)


为服务指定地址  ( 逻辑地址和物理地址 )

1:通过代码方式指定地址.

2:通过配置指定地址.

默认的情况下,监听地址与终结点地址是统一的。只有在逻辑地址和物理地址相互分离的情况下,才需要指定不同于终结点地址的监听地址.(也就是说服务器启动之后,我们上面配置服务器终结点  http://127.0.0.1:6666/calculatorservice   这个地址会被服务器不断的监听。 我们上面的例子都是  这种方式  去 监听的,因为我们上面的例子并没有配置 物理地址。)

在WCF中,每个终结点(服务端以及客户端的终结点)都包含两个不同的地址:逻辑地址和物理地址。逻辑地址就是以终结点Address属性表示的地址。(我们上面 第一讲与第二讲 的例子配置的都是 逻辑地址 )

至于物理地址,对于消息发送端来讲,就是消息被真正发送的目的地址:而对于消息的接收端来讲,就是监听器真正监听的地址。

之前第一讲的时候 我们 使用代码方式完成服务端的  服务寄宿  时候需要 填写  A,B,C

其实后面还有一个选项参数  ,就是我们的 物理地址  参数了,只不过之前我们都没有写

[ 3-01 ]

看上图  我们 服务器的 物理地址 配置就是这里,如果这里配置了  物理地址  ,那么服务器的监听地址就不是配置的 参数  A 了,而是配置的物理地址。

[ 3-02 ]

我们配置一下服务端的 (以代码的方式去配置)

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Security.Policy;
 5 using System.ServiceModel;
 6 using System.ServiceModel.Description;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 using Contracts;
10 using Services;
11
12 namespace Hosting
13 {
14     class Program
15     {
16         static void Main(string[] args)
17         {
18             //首先提供一个主机进程,实际上就是完成寄宿的主机( CalculatorService 完成了对契约的实现,所以我们这里就寄宿就寄宿它了 )
19             using (var host = new ServiceHost(typeof(CalculatorService)))
20             {
21                 /*
22                  然后 当我们把寄宿后,就要完成我们的EndPoint(终结点) 了,之前提过EndPoint=A,B,C 那么这里就要绑定了
23                  之前的图片 [ 1-05 ] 已经展示 过这个 EndPoint
24                  这里的 WSHttpBinding 就是 指定 HTTP 协议 当然还有很多种,后面说到
25                  添加终结点 首先 C,然后 B 最后 A
26                  */
27                 host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:6666/calculatorservice", new Uri("http://127.0.0.1:8888/calculatorservice"));
28
29                 //这里检测 元数据 为不为空  这里的元数据也不管是什么东西,下面我们说到
30                 if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
31                 {
32                     //也就是说这里我们是以元数据的形式发布出去进行客户端与服务器的交互
33                     //控制服务元数据和相关信息的发布
34                     ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
35                     behavior.HttpGetEnabled = true;//是否可以通过 HTTP Get 形式 去访问
36                     // 元数据的地址,可以通过这个地址 在  浏览器中 进行访问
37                     behavior.HttpGetUrl = new Uri("http://127.0.0.1:6666/calculatorservice/metadata");
38                     //添加到元数据中去
39                     host.Description.Behaviors.Add(behavior);
40                 }
41                 //指定一个事件,当服务启动之后 需要做什么,这里指定一个委托,在 Open 成功后,就执行这里的事件
42                 host.Opened += (sender, eventArgs) => Console.WriteLine("服务已经启动,按任何按钮停止");
43                 //开启服务
44                 host.Open();
45                 Console.Read();
46             }
47         }
48     }
49 }

[ 3-03 ]

当然也可以使用 配置文件的方式去配置服务端

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3   <system.serviceModel>
 4     <behaviors>
 5       <serviceBehaviors>
 6         <behavior name="metadataBehavior">
 7           <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:9999/calculatorservice/metadata"/>
 8         </behavior>
 9       </serviceBehaviors>
10     </behaviors>
11     <services>
12       <service behaviorConfiguration="metadataBehavior" name="Services.CalculatorService">
13         <!--服务端 配置  物理地址  也就是  真正监听的地址  listenUri=""  -->
14         <endpoint address="http://127.0.0.1:9999/calculatorservice"
15                   listenUri="http://127.0.0.1:8888/calculatorservice"
16                   binding="wsHttpBinding" contract="Contracts.ICalculator"></endpoint>
17       </service>
18     </services>
19
20   </system.serviceModel>
21 </configuration>

那么我们客户端的配置就是 (  这里就说WebConfig 去配置物理地址了。代码方式配置 物理地址没有找到,如果有朋友知道通知一声,谢谢!  )

[ 3-04 ]

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3   <system.serviceModel>
 4     <behaviors>
 5       <endpointBehaviors>
 6         <behavior name="clientViaBehavior">
 7           <!--客户端配置物理地址 (也就是信息具体发送地址) viaUri 这个 参数 -->
 8           <clientVia viaUri="http://127.0.0.1:8888/calculatorservice"/>
 9         </behavior>
10       </endpointBehaviors>
11     </behaviors>
12     <client>
13       <endpoint behaviorConfiguration="clientViaBehavior" address="http://127.0.0.1:9999/calculatorservice"
14                 binding="wsHttpBinding" contract="Contracts.ICalculator" name="calculatorservice"></endpoint>
15     </client>
16   </system.serviceModel>
17 </configuration>

(1)服务端逻辑地址与物理地址。

对于消息接收放的终结点来讲,物理地址就是监听地址。

public ServiceEndpoint AddServiceEndpoint(string implementedContract,Binding binding,string address,Uri listenUri)

(2):客户端逻辑地址与物理地址

对于消息的发送端来讲,物理地址其实就是消息发送的真正目的地址。通过

ClientVia定义客户端URI代表物理地址.


为服务指定地址  ( 基地址与相对地址)
这里说白了 就是 将  地址 分开来写  
例如  我们上面配置的    http://127.0.0.1:8888/calculatorservice  这个 服务器 终结点地址   把它 拆开来写   http://127.0.0.1:8888  就是  基地址    而  calculatorservice 就是相对地址  可以这么理解
 
我们来看下程序中怎么做:
我们先看以 代码的方式 去配置基地址  
服务端 
[ 3-05 ]
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 using System.ServiceModel;
 5 using System.ServiceModel.Description;
 6 using Contracts;
 7 using Services;
 8
 9 namespace Hosting
10 {
11     class Program
12     {
13         static void Main(string[] args)
14         {
15             //两个不同协议的基地址
16             Uri[] baseAddress = new Uri[2];
17             baseAddress[0] = new Uri("http://127.0.0.1:9999");
18             baseAddress[1] = new Uri("net.tcp://127.0.0.1:8888");
19
20             using (ServiceHost host = new ServiceHost(typeof(CalculatorService), baseAddress))
21             {
22                 //两个不同协议的相对地址
23                 host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "calculatorservice");
24                 host.AddServiceEndpoint(typeof(ICalculator), new NetTcpBinding(), "calculatorservice");
25
26                 host.Opened += delegate
27                 {
28                     Console.WriteLine("服务已经启动,请按任意键中止服务");
29                 };
30                 host.Open();
31                 Console.Read();
32             }
33         }
34     }
35 }

客户端

[ 3-06 ]

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.ServiceModel;
 6 using Contracts;
 7
 8 namespace Client
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             //这里按照之前不变
15             using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(new WSHttpBinding(), "http://127.0.0.1:9999/calculatorservice"))
16             {
17                 ICalculator proxy = channelFactory.CreateChannel();
18                 using (proxy as IDisposable)
19                 {
20                     Console.WriteLine("x+y={2} when x={0} and y={1}", 1, 2, proxy.Add(1, 2));
21                     Console.ReadKey();
22                 }
23             }
24         }
25     }
26 }

代码的方式  可以不去管 Appconfig 的配置
再看  以 appconfig 配置的 方式 去配置  基地址与相对地址
服务端  Program.cs
[ 3-07 ]
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Text;
 4 using System.ServiceModel;
 5 using System.ServiceModel.Description;
 6 using Contracts;
 7 using Services;
 8
 9 namespace Hosting
10 {
11     class Program
12     {
13         static void Main(string[] args)
14         {
15             //以下是通过配置文件更改了终结点的添加和服务行为的定义.
16             using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
17             {
18                 host.Opened += delegate
19                 {
20                     Console.WriteLine("CalculaorService已经启动");
21                 };
22                 host.Open();
23                 Console.Read();
24             }
25         }
26     }
27 }

服务端  App.config

[ 3-08 ]

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3   <system.serviceModel>
 4     <services>
 5       <service name="Services.CalculatorService">
 6         <!--配置两个不同协议的想相对地址-->
 7         <endpoint address="calculatorservice" binding="wsHttpBinding" contract="Contracts.ICalculator"></endpoint>
 8         <endpoint address="calculatorservice" binding="netTcpBinding" contract="Contracts.ICalculator"></endpoint>
 9         <host>
10           <baseAddresses>
11             <!--配置两个不同协议的基地址-->
12             <add baseAddress="http://127.0.0.1:9999"/>
13             <add baseAddress="net.tcp://127.0.0.1:8888"/>
14           </baseAddresses>
15         </host>
16       </service>
17     </services>
18   </system.serviceModel>
19 </configuration>

服务端配置好了

客户端  Program.cs

[ 3-09 ]

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.ServiceModel;
 6 using Contracts;
 7
 8 namespace Client
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorservice"))
15             {
16                 ICalculator proxy = channelFactory.CreateChannel();
17                 using (proxy as IDisposable)
18                 {
19                     Console.WriteLine("x+y={2} when x={0} and y={1}", 1, 2, proxy.Add(1, 2));
20                     Console.ReadKey();
21                 }
22             }
23         }
24     }
25 }

客户端  App.config

[ 3-10 ]

1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3   <system.serviceModel>
4     <client>
5      <endpoint  address="http://127.0.0.1:9999/calculatorservice" binding="wsHttpBinding" contract="Contracts.ICalculator" name="calculatorservice"></endpoint>
6       <!--<endpoint address="net.tcp://127.0.0.1:8888/calculatorservice" binding="netTcpBinding" contract="Contracts.ICalculator" name="calculatorservice"></endpoint>-->
7     </client>
8   </system.serviceModel>
9 </configuration>

从上面的代码中我们可以看到  服务端 写了 两个 不同协议的监控地址  这是可以的,但不能配置同一协议的 两个不同的地址 

而客户端则只能写一个 地址,不管是HTTP协议还是TCP谐音,有且只能写一个地址。

基地址与相对地址

除了以绝对路径的方式指定某个服务的终结点地址外,还可以通过”基地址+相对地址”的方式进行设置.对于一个服务来说,可以指定一个或多个基地址,但是对一种传输协议类型,只能就有一个唯一的基地址。

好了  我们的补充 就到这里了


我们来看我们这节的主要知识:服务契约

服务契约:

是相关操作的集合.

契约就是双方或多方就某个关注点达成的一种共识,是一方向另一方的一种承诺。签署了某个契约就意味着自己有义务履行契约中规定的各项规定,一旦违约势必影响契约双方的正常交互.

我们主张通过抽象将接口和实现相互分离,鼓励接口的依赖,避免基于实现的依赖。接口是稳定的,而实现则是易变的,基于接口的服务调用能够更有效地应对实现的变化带来的影响。

接口从本质上就是一种契约,当某个类实现了某个接口,就相当于签署了一份契约。所以契约关心的是“我能做到”,不在于”我如何做到”。所以,服务契约是以接口的形式进行定义的。

有了服务契约,那我们如何去描述 服务契约?

WSDL、XSD与服务契约

对于服务契约来说,它涉及的参与者就是服务的提供者和服务的消费者,服务的提供者通过服务契约的形式将服务公布出来,服务的消费者通过服务契约进行服务的消费。那么,要保证服务的正常消费,有一个根本的前提:服务的消费者能够正确“理解”服务提供者公布出来的服务契约。

也就是必须有一个统一的标准:XML因其简单,表意能力强,已经成为了事实上的标准。如何表达通过XML的数据结构?XSD是最好的选择。而对于WEB服务的描述,它有自己专门的标准,最基本的就是WSDL。

所以,如果希望服务契约能被基于不同平台的客户端所理解的话,就应以一种平台无关的标准进行描述,而在WCF中服务契约就是最终可以通过WSDL描述的。

就是我们上面说的 元数据

看这里的 GIF 图片   :

[ 3-11 ]

[ 3-12 ]

[ 3-13 ]

仔细看这里的XML:

[ 3-14 ]

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <xs:schema xmlns:tns="  " xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace=" " elementFormDefault="qualified">
 3   <xs:element name="Add">
 4     <xs:complexType>
 5       <xs:sequence>
 6         <xs:element name="x" type="xs:double" minOccurs="0"/>
 7         <xs:element name="y" type="xs:double" minOccurs="0"/>
 8       </xs:sequence>
 9     </xs:complexType>
10   </xs:element>
11   <xs:element name="AddResponse">
12     <xs:complexType>
13       <xs:sequence>
14         <xs:element name="AddResult" type="xs:double" minOccurs="0"/>
15       </xs:sequence>
16     </xs:complexType>
17   </xs:element>
18 </xs:schema>

这很明显的 描述了  我们的服务契约:   有一个Add 的方法   两个参数   x,y    ,以及返回值 也是  double 类型


转载于:https://www.cnblogs.com/xulang/p/5465094.html

第三讲:WCF介绍(3)相关推荐

  1. 《WCF技术内幕》翻译5:第1部分_第1章_蓝月亮:WCF介绍和本章小结

    WCF介绍   在上世纪90年代微软和其他公司看到了互联的普遍需求和面向服务的普遍概念.那时,还没有被普遍接受的消息标准,结果,就没有平台.应用程序编程接口API.或者能够让开发者轻易创建面向服务的应 ...

  2. [WCF Step by Step 读书笔记] Chapter01 WCF 介绍

    下面通过搭建一个书中完整的WCF的例子阐述WCF: 1. 建立一个ASP.NET WebSite的的空工程ProductService. 2. 添加一个Class Library的工程,删除其.cs文 ...

  3. 《WCF技术内幕》翻译1:《WCF技术内幕》目录和作者简介

    翻译序言: 我现在推荐一本很好的WCF学习书籍:<Inside Microsoft Windows Communication Foundation>.Justin Smith先生所著.2 ...

  4. WCF分布式开发步步为赢(0):WCF学习经验分享,如何更好地学习WCF?

    WCF分布式开发学习,应该从哪里开始? 微软WCF Web服务 Web API学习群 339444457 微软ASP.NET MVC 4 Web编程群     44206115 学习WCF是不是就不需 ...

  5. [zz]WCF分布式开发步步为赢(0):WCF学习经验分享,如何更好地学习WCF?

    WCF分布式开发学习,应该从哪里开始?    学习WCF是不是就不需要学习Enterprise Sevices(COM+).Net Remoting.Web Service(ASMX).WSE3.0和 ...

  6. WCF必知必会以及与Webapi的区别

    快速阅读 介绍wcf中的信息交换模式MEP以及数据在传输过程中的序列化,endpont的介绍和wcf的三种实例模式以及安全模式 以及和Webapi的简单对比 wcf介绍 支持跨平台,多种协议 tcp, ...

  7. 《我的WCF之旅》博文系列汇总

    WCF是构建和运行互联系统的一系列技术的总称,它是建立在Web Service架构上的一个全新的通信平台.你可以把它看成是.NET平台上的新一代的Web Service.WCF为我们提供了安全.可靠的 ...

  8. WCF学习经验分享,如何更好地学习WCF?

    WCF分布式开发学习,应该从哪里开始? 学习WCF是不是就不需要学习Enterprise Sevices(COM+).Net Remoting.Web Service(ASMX).WSE3.0和MSM ...

  9. 【WCF】WCF框架学习

    WCF介绍 Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台,本质是一套软件开发包,与平 ...

最新文章

  1. 开发日记-20190427
  2. 怎样cp文件夹时忽略指定的文件夹和文件
  3. C/C++|Qt工作笔记-4种方法判断当前对象(类)名或标识(继承发,typeid法,元对象className()法,Q_CLASSINFO法)
  4. 基于box2dWeb开发的切水果游戏总结
  5. python 根据网址获取股票
  6. 单循环链表(用尾指针表示)
  7. io 流 txt本地生成
  8. 怎么通过$a获取到$b?某豹面试题
  9. idea原生ajax数据处理(增删改查)
  10. 电脑围棋领域的研究概述
  11. BigDecimal类型加减乘除运算(Java必备知识)
  12. Oracle视图(View)----------------数据库中虚拟的表
  13. 【Linux】shell脚本实战-使用shell进行数学运算
  14. 12306网站车票爬取
  15. 怎么设置cmd 以管理员身份运行
  16. 华为推送 坑点 自定义intent
  17. Linux系统创建vlan教程,linux vlan配置详解
  18. 单月涨粉30w+,他们掌握引流法宝,小红书1月创作趋势是什么?
  19. 逻辑回归(Logistic Regression)
  20. Adam优化算法中的指数移动平均

热门文章

  1. 3 文件读写 计时 我的烂电脑在1S钟能写70多MB的数据
  2. Exchange2003-2010迁移系列之六,配置及配置第二台Exchange CAS/HUB服务器
  3. U盘无法安全正常弹出和删除如何处理
  4. git中Please enter a commit message to explain why this merge is necessary.
  5. 高效的找出两个List中的不同元素
  6. GitHub教程学习笔记3---分支管理
  7. 2.0 pomelo-treasure官方demo的使用
  8. Tomcat 集群中 实现session 共享的三种方法
  9. 青蛙跳台阶问题——剑指offer
  10. PHP Web System Optimization(undone)