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服务应用便开始了服务调用请求的监听工作.此外,服务寄宿将服务描述通过元数据的形式发布出来,相应的客户端就可以获取这些元数据.接下来我们来创建客户端 ...
随机推荐
- 【CF1243A】Maximum Square【贪心】
题意:给你n个长度为ai的木板,求最大能拼成的矩形为多大 题解:显然贪心每次选最大的进去拼,那么剧需要枚举矩形长度x,看最长的k个能够拼出长度为x的矩形即可 #include<iostream& ...
- python 数字系列-复数的数学运算
复数的数学运算 问题 你写的最新的网络认证方案代码遇到了一个难题,并且你唯一的解决办法就是使用复数空间. 再或者是你仅仅需要使用复数来执行一些计算操作. 解决方案 复数可以用使用函数 complex( ...
- 牛客提高D4t2 卖羊驼
分析 不难想到dp[i][j]表示前i个数分了j组的最大值 我们发现这个dp状态有决策单调性 g[i][j]表示对于第i个数它的第j位最近出现的位置 每次一定从这些点转移 预处理即可 似乎还可以做到1 ...
- Mac010--IDEA安装及应用
Mac--IDEA安装及应用 应用IDEA,首先确保已安装如下环境: JDK:JDK是整个java开发的核心,它包含了JAVA的运行环境,JAVA工具和JAVA基础的类库(安装 & 配置环境变 ...
- Maximum Subarray(最大连续子序列和)
https://leetcode.com/problems/maximum-subarray/ 思路: 如果全为负值,那么取最大值 如果有非负值,那么我们依次计算到当前位置为止的最大值.假设有n个元素 ...
- [Python3 填坑] 013 几个类相关函数的举例
目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 issubclass() 2.2 isinstance() 2.3 hasattr() 2.4 getattr() 2.5 setatt ...
- hive 排序
1.全局排序(order by) Order by:全局排序,只有一个reducer ASC(ascend):升序(默认) DESC(descend):降序 2.每个MR内部排序(sort by) s ...
- Codeforces 1166E(思维)
题面 有一个长度为n的序列a,有m次操作.每一次操作一个人选a的一个子集x,另一个人会选x的补集y.且x集合中的数的最小公倍数比y集合中的数的最小公倍数大.现在给出所有x,判断是否有一个序列a满足条件 ...
- [暑假集训Day4T1]羊圈
ZYC同志开农场了????? 二分答案. 对于每一个二分出来的答案对其进行检查(check),检查是否有一个长度大于m的字段和的平均值大于mid.方法如下:先把原数组的每一个元素减去mid,储存进一个 ...
- luoguP2123 皇后游戏(贪心)
luoguP2123 皇后游戏(贪心) 题目 洛谷题目chuanso 题解 有一篇好题解,我就懒得推式子了,毕竟打到电脑上还是很难的 牛逼题解传送门 code #include<iostream ...