2.WCF学习--地址
一、URI(统一资源标识)
web服务可视为一种网络资源,并且可以通过一个URI来进行唯一标识。而服务通过终结点的形式发布出来,我们所说的一个服务在大部分场景中实际上指的是服务的某个终结点。终结点的核心就是一个URI,它可以作为终结点的唯一标识,还具有路由或寻址的功能。地址对应的URI不仅代表了服务所在位置,也代表了消息路由的目标地址
URI结构:
[传输协议(Scheme)]://[主机名称|域名|IP地址]:[可选端口]/[资源路径]
例如:
http://artech.com:9999/myservices/calculatorservice.svc
二、HTTP/HTTPS
HTTP全称为 HyperText Transfer Protocol(超文本传输协议),是建立在TCP/IP簇上的应用层协议。由于其简单、易用的特性,已经成为事实上的Internet标准。
1、TTTP提供简单的请求-回复消息传输方式
2、HTTP是无状态的,每次请求都是互相独立的
3、HTTP是无连接的,基于HTTP的数据传输无须事先打开连接
HTTPS全称为HypeText Transfer Protoco over Secure Socket Layer(安全超文本传输协议),它采用了SSL(Secure Socket Layer) 的HTTP。而SSL是一个进行数据加密的协议,很多安全性要求高的网站都采用HTTPS。WCF通过HTTPS实现了基于HTTP的传输安全(Transport Security)
注意:HTTP和HTTPS的URI分别使用http和https作为传输协议前缀,默认使用的端口号分别为80和443
http://artech.com/myservices/calculatorservice.svc = http://artech.com:80/myservices/calculatorservice.svc
三、Net.TCP
TCP全称为Transport Control Protocol(传输控制协议),在整个TCP/IP簇上处于核心地位。从整个协议分层结构来看,位于应用层之下,网络层(IP协议)之上。
1、TCP是基于连接的传输协议,在开始进行数据传输之前,通过客户端和服务端之间的3次“握手”创建连接;在结束传输之后,通过4此“握手”终止连接
2、TCP是有状态的,由于数据传输在一个确定的连接中进行,因此可以保持每次数据传输的状态
3、TCP支持全双工通信,一旦连接成功创建,数据就可以在两个方向上同时传输
4、TCP支持可靠通信,IP协议本身提供的数据是不可靠的,数据的可靠传输只能通过TCP来保证
注意:WCF通过NetTcpBinding支持基于TCP的传输。对于TCP的URI,其传输协议前缀为net.tcp://。默认端口号为808
四、Net.Pipe
命名管道(Named Pipes)是Windows平台及UNIX系统下实现跨进程通信(Inter Process Communication,IPC)的标准实现方式。虽然命名管道本身可以实现跨机器的通讯,但是WCF只将命名管道专门用于同一台机器的跨进程的通讯,所以基于命名管道的URI的主机名称|域名|IP地址部分只能是本机的机器名、localhost、127.0.0.1,基于命名管道的URI以net.pipe为前缀,而在基于同一台机器的不同进程间通信中,端口没有任何意义
五、Net.Msmq
消息队列(Message Queuing,也称MSMQ),是微软对消息服务领域的开创性尝试。由于消息队列采用了特殊的通信机制,因此对于改善和提高系统的可扩展性和高可用性具有重要的意义。
按照可访问行划分如下:
1、公共消息队列:公有队列的名称被注册到AD域中,所以我们无须指定队列所在的机器名称就可以访问队列。当将某个公有队列从一台机器转移到另一台机器时,访问该队列的应用可以保持不变。公有队列还可以提供基于域账号的Windows认证机制,所以对于正式发布的应用来说,通常采用公有队列
2、私有消息队列:因为公有队列需要注册到AD域中所以它只能用于域(Domain)模式下。在工作组(Work Group)模式下,只能使用私有队列。而访问私有队列需要指定包含队列所在机器名称的路径
注意:WCF下基于消息队列的URI具有net.msmq前缀。在主机名称和队列名称通过字符Private标识私有队列,而对于公有队列的URI,表示队列类型部分则不是必需的
net.msmq://artech.com/myservices(公有队列)
net.msmq://artech.com/Private/myservices(私有队列)
六、EndpointAddress
终结点在WCF应用编程接口中通过System.ServiceModel.Description.ServiceEndpoint类型表示,ServiceEndpoint核心属性如下:
public class ServiceEndpoint
{
public EndpointAddress Address { get; set; } //地址
public Binding Binding { get; set; } //绑定
public ContractDescription Contract { get; set; } //契约
}
表示终结点地址的Address属性是一个类型为System.ServiceModel.EndpointAddress的对象(地址核心功能:服务标识/定位、辅助寻址和服务身份标识)
public class EndpointAddress
{
public AddressHeaderCollection Headers { get; }//辅助寻址(地址包头列表存放一些寻址信息)
public Uri Uri { get; } //服务与定位(可以是物理地址,也可以是逻辑地址)
public EndpointIdentity Identity { get; } //身份标识(服务身份,被客户端用于认证服务)
}
EndpointIdentity:客户端终结点通过地址的该属性表示自己希望调用服务的真实身份。调用前,服务端将自己的凭证(Windows凭证、X.509证书凭证等)提供给客户端,而客户端通过以EndpointIdentity对象代表的服务身份与凭证进行比较,来验证正在调用的服务确实是自己所希望调用的服务
七、服务端终结点地址
WCF通过ServiceHost完成宿主的寄宿,而被寄宿的服务通过添加到ServiceHost的终结点暴露出来成为可被调用寻址和调用的资源
public class ServiceHost : ServiceHostBase
{
public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address);
public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri);
public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address);
public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri);
}
ServiceHostBase是ServiceHost的基类
public abstract class ServiceHostBase : CommunicationObject, IExtensibleObject<ServiceHostBase>, IDisposable
{
public virtual void AddServiceEndpoint(ServiceEndpoint endpoint);
public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address);
public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri);
public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address);
public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri);
}
implementedContract:表示服务契约类型全名的字符串
listenUri:服务的监听地址
using (ServiceHost host = new ServiceHost(typeof(Service.CalculatorService)))
{
//添加终结点(一个基于WSHttpBinding绑定的终结点 终结点地址:http://127.0.0.1:3721/calculatorservice 服务契约的类型:ICalculator)
host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:3721/calculatorservice");
host.AddServiceEndpoint(typeof(ICalculator), new NetTcpBinding(), "http://127.0.0.1:3721/calculatorservice");
}
添加的终结点我们可以通过他的只读属性Description获取
public abstract class ServiceHostBase : CommunicationObject, IExtensibleObject<ServiceHostBase>, IDisposable
{
public ServiceDescription Description { get; }
}
ServiceDescription:表示整个服务的描述(终结点列表)
public class ServiceDescription
{
public string Name { get; set; }
public string Namespace { get; set; }
public KeyedByTypeCollection<IServiceBehavior> Behaviors { get; }
public string ConfigurationName { get; set; }
public ServiceEndpointCollection Endpoints { get; }
public Type ServiceType { get; set; }
public static ServiceDescription GetService(Type serviceType);
public static ServiceDescription GetService(object serviceImplementation);
}
除了使用代码添加终结点还可以使用配置文件方式配置终结点
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="calculatorservice/metadata" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="metadataBehavior" name="Service.CalculatorService">
<endpoint address="calculatorservice" binding="wsHttpBinding"
bindingConfiguration="" name="Service.CalculatorService" contract="Service.Interface.ICalculator" />
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:9999" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
这样我们就不需要再使用代码来添加终结点了
using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
{
host.Opened += delegate
{
Console.WriteLine("CalculatorService 启动,按任意键终止服务!");
};
host.Open();//开启服务
Console.Read();
}
注意:WCF在进行基地址和相对地址匹配的时候,会根据终结点的绑定类型从基地址列表中获取与传输协议相匹配的基地址
地址终结点共享:一般情况下,服务实现一个单一的契约接口,所以服务的所有终结点共享相同的契约。既然这些终结点具有相同的契约,他们的地址就不可能相同。但是对于一个实现了多个服务契约接口的服务来说,多个基于不同契约的终结点就可以共享相同的地址,但是必须共享相同的绑定对象实例(这个地方有待完善,没有验证。。。)
例如我们有两个契约接口 ICalculator1和ICalculator2 服务契约的实现类 CalculatorService
using (ServiceHost host = new ServiceHost(typeof(Service.CalculatorService)))
{
WSHttpBinding binding = new WSHttpBinding();
//添加终结点(一个基于WSHttpBinding绑定的终结点 终结点地址:http://127.0.0.1:3721/calculatorservice 服务契约的类型:ICalculator)
host.AddServiceEndpoint(typeof(ICalculator1), binding , "http://127.0.0.1:3721/calculatorservice");
host.AddServiceEndpoint(typeof(ICalculator2), binding , "http://127.0.0.1:3721/calculatorservice");
}
2.WCF学习--地址的更多相关文章
- WCF学习之旅—WCF服务部署到应用程序(十)
上接 WCF学习之旅—WCF寄宿前的准备(八) WCF学习之旅—WCF服务部署到IIS7.5(九) 五.控制台应用程序宿主 (1) 在解决方案下新建控制台输出项目 ConsoleHosting.如下 ...
- WCF学习之旅—WCF服务的WAS寄宿(十二)
上接 WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一) 八.WAS宿主 IIS ...
- WCF学习之旅—TcpTrace工具(二十六)
止文(WCF学习之旅—TcpTrace工具(二十五))介绍了关于TcpTrance的一种使用方式,接下来介绍第二种使用方式. 三.通过ListenUri实现基于tcpTracer的消息路由 对于路由的 ...
- WCF学习之旅—TcpTrace工具(二十五)
前面的几篇文章,我们学习了怎么开发WCF应用程序与服务,也学习了如何进行WCF的配置.对于Web Service与WCF服务应用,服务端与客户端的通信是通过收发SOAP Message进行,我们如何有 ...
- WCF学习之旅—实现支持REST客户端应用(二十四)
WCF学习之旅—实现REST服务(二十二) WCF学习之旅—实现支持REST服务端应用(二十三) 在上二篇文章中简单介绍了一下RestFul与WCF支持RestFul所提供的方法,及创建一个支持RES ...
- WCF学习之旅—TCP双工模式(二十一)
WCF学习之旅—请求与答复模式和单向模式(十九) WCF学习之旅—HTTP双工模式(二十) 五.TCP双工模式 上一篇文章中我们学习了HTTP的双工模式,我们今天就学习一下TCP的双工模式. 在一个基 ...
- WCF学习之旅—HTTP双工模式(二十)
WCF学习之旅—请求与答复模式和单向模式(十九) 四.HTTP双工模式 双工模式建立在上文所实现的两种模式的基础之上,实现客户端与服务端相互调用:前面介绍的两种方法只是在客户端调用服务端的方法,然后服 ...
- WCF学习之旅—WCF第二个示例(七)
三.创建客户端应用程序 若要创建客户端应用程序,你将另外添加一个项目,添加对该项目的服务引用,配置数据源,并创建一个用户界面以显示服务中的数据. 在第一个步骤中,你将 Windows 窗体项目添加到解 ...
- WCF学习之旅——第一个WCF示例(三)
第五步:创建客户端 WCF应用服务被成功寄宿后,WCF服务应用便开始了服务调用请求的监听工作.此外,服务寄宿将服务描述通过元数据的形式发布出来,相应的客户端就可以获取这些元数据.接下来我们来创建客户端 ...
随机推荐
- JS占位符替换
String.prototype.format = function() { if(arguments.length === 0) return this; var obj = arguments[0 ...
- python 文件读写操作打开模式
‘r’:只读.该文件必须已存在. ‘r+’:可读可写.该文件必须已存在,写为追加在文件内容末尾. ‘rb’:表示以二进制方式读取文件.该文件必须已存在. ‘w’:只写.打开即默认创建一个新文件,如果文 ...
- 关于Spring中BeanUtils的一次使用问题记录
1.问题描述:今天在进行前后端联调的时候,发现商品图片不能正常显示: 2.排查过程:查看浏览器控制台,发现调用接口返回的数据关于图片的字段未返回数据: 然后,又跑了一下Dao层的单元测试,从 ...
- CentOS-7.4(1708)release notes发行注记
Red Hat Enterprise Linux 当前的最新版本是 7.3. Red Hat Enterprise Linux 7 当前仅支持 64 位CPU:64-bit AMD.64-bit In ...
- JavaScript-[[prototype]]的另一种理解
[[prototype]]简介 javascript 中每一个对象都会有一个特殊的内置属性[[prototype]],这个就是对其他对象对引用.有了这个作为基础去关联其他对象,就能理解继承机制.Chr ...
- Jquery append() 添加多次同个元素时,只有一次作用,如何解决?
这是一个简单的table <table id="mytable"> <!-- 这里将要动态加载tr数据 --> </table> 这是一个模版t ...
- Nginx 实现全站 HTTPS(基于 Let's Encrypt 的免费通配符证书)
单域名证书的生成可以 参考这里. acme.sh 项目中文文档 Let's Encrypt 在 18 年 1 月份推出了 ACME v2,支持通配符域名证书,对小网站.个人站长的友好度进一步增加. 常 ...
- 第 3 章 前端基础之JavaScript
一.JavaScript概述 1.javascripts的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中),后将其改名ScriptE ...
- Java8数据流
流/Stream是在JAVA8中引入的一个抽象,可以处理类似SQL语句声明数据. 例如,考虑下面的SQL语句. SELECT max(salary),employee_id,employee_name ...
- HTML5-Classlist样式操作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...