DotNet关键知识点——WCF篇(三)
关于服务的部署和使用。
1. 服务的部署
控制台部署
配置简单。可配置一个基地址。
配置文件app.config用于配置服务端点等。
以下的IIS和WAS均支持消息首次启动;不需要设置基地址(基地址由网站的虚拟路径决定)
IIS部署
.svc文件,必须位于App_Code子目录:
C#代码文件也需要在App_Code中;而如选择使用编译后的文件,则将其放在bin子目录中。
配置文件web.config也位于App_Code中。
WAS部署
除了支持HTTP外,还支持其他协议如TCP,消息队列MSMQ,命名管道等。
使用方法接近IIS部署。
非HTTP支持(仅Windows Vista以上):
1. 在控制面板中设置…;
2. 在控制面板中确认SMSvcHost.exe接听的适配服务(Listener Adapter Services)运行:Net.Pipe Listener Adapter,Net.Tcp Listener Adapter和Net.Tcp Port Sharing Service。(.NET MSMQ Listener Adapter需要在MSMQ server core安装后才可启用)
以下IIS 7.0工具appcmd.exe位于system32/inetsrv/
appcmd.exe set site "网站名" –+bindings.[protocol='net.tcp', bindingInformation='808:*']
位于system32/inetsrv/config的WAS配置文件applicationHost.config随之改变,在bindings标记中增加一行:
为一个具体的服务应用使能协议:
appcmd.exe set app "网站名/应用名" /enabledProtocols:http,net.tcp
配置MSMQ
1. 命名一个队列,名称必须为"应用名/svc文件名"
2. 默认处理MSMQ的NT服务使用NETWORK SERVICE账户登录,通过配置工具为此账户设置配置权限,使其为可检视和收取信息
3. 在服务配置文件中添加一个对应端口,地址形如 "net.msmq://主机路径/应用名/svc文件名名",绑定名netMsmqBinding。
继承ServiceHost
WCF提供ServiceHostFactory类厂用于在收到请求时动态创建具体的service host实例。
重载void OnOpening()和void OnClosing()可以定义启动和退出时的行为。
2. 在托管应用中开展服务
WCF允许在任何托管应用(Managed Application)中运行服务,包括:
- - 控制台
- - Windows服务
- Windows窗体应用或WPF应用
- WCF内建的命令行工具
控制台
运行比较简单且已经叙述过。
Windows服务 - 1. 用Windows服务模板,服务继承自ServiceBase
2. 在服务的构造函数中设置ServiceName属性,在void Main()中创建并运行服务ServiceBase.Run(new 服务类型())
3. 在void OnStart(string[] args)中重建ServiceHost对象运营服务,并调ServiceHost.Open()
4. 在void OnStop()中调用ServiceHost.Close()关闭服务
5. 编写安装器(继承自Installer,使用RunInstallerAttribute(true)标记),创建ServiceProcessInstaller和ServiceInstaller,分别设置Account和ServiceName属性,最后调用Installer.Add(…)加入到安装过程中。
6. 编写配置文件app.config
7. 用"installutil 服务路径(.exe文件)"安装服务。
使用WCF内建工具
WcfSvcHost.exe /service:服务约定输出二进制文件.dll /config:配置文件路径(app.config)
3. 服务的使用
获得代理类(服务由WCF运营)的四种方法:
方法 说明 方法 从服务元数据获取 使用svcutil.exe
灵活性最大【导出】
/l[anguage]:c#…
/o[ut]:<文件> 输出的代码,默认为WSDL定义名/服务名/…
/config:<文件> 配置文件默认为output.config
/mergeConfig 表示是否为融合到已有的配置文件中
/n[amespace]: 从WSDL或XML模式的名空间转换到.NET代码中的名空间, 如:"*, SomeNS"用以将所有名空间均转换为SomeNS
/messageContract 输出消息约定(/mc)
/async 同时也生成异步方法
/seralizer:XmlSerializer,生成支持XML序列化的数据类型
【使用】
创建生成的代理类实例,使用该实例。通过Visual Studio的服务引用添加 界面友好,本质上使用svcutil.exe 不支持XML序列化数据类型 【导出】根据界面选项
【使用】同上,使用代理手工创建 【导出】
服务约定接口类似服务器端定义
创建一个代理类,继承ClientBase<服务接口名>,并实现服务接口
实现构造函数:base(binding, addr)和base(string endpointCfgName)
实现具体的操作函数,均调base.Channel.操作函数名(参数系)
【使用】
创建Binding类和端点地址EndpointAddress
创建代理类(binding, addr),使用该代理类实例用ChannelFactory动态添加 调用ChannelFactory<服务接口名>(绑定, 地址),创建一个厂对象
调用厂对象的CreateChannel(),返回一个服务接口实例
此后即可使用该实例
XML序列化
XML序列化输出:如果服务约定支持XML,则比较方便;否则在客户端需要添加附属设施实现序列化,如用手工创建则非常繁琐,因此通常只能用svcutil.exe工具。
异步导出
生成的代理类中增加BeginXXX(一般参数, callback, userdata)和EndXXX(IAsyncResult)。在回调中从IAsyncResult.AsyncState得到userdata,通常就是代理对象,然后可以调用EndXXX(…),得到返回的对象。
关闭代理
调用Close()或Dispose()方法,或在using中使用(发生异常时自动释放),只是当用接口时,采用如下方式:
ISomeService proxy = new SomeService();
using (proxy as IDisposable)
{ … }
双工
1. 实现服务约定的代理,并继承自DuplexClientBase<服务约定接口名>,构造函数调用base(InstanceContext ic, binding, addr)
2. 实现返回消息服务约定接口(IxxxHandler)
3. 创建一个返回消息服务约定实例,并将其代入构造InstanceContext实例
4. 用上述实例构造代理
通常为了整合客户端的一些反复操作,可以设立服务中介(Service Agents)。
出错处理
在服务器端抛出的FaultException<内嵌类型>,在客户端导出约定接口也类似定义标记,同时必要时也导出内嵌类型。在使用时,只要捕捉这个FaultException<内嵌类型> fault异常即可,fault.Detail就指向内嵌类型实例。
4. 使用非WCF提供的服务
只能通过标准的WSDL,必须使用svcutil.exe工具或采用VS的添加服务引用的方式。互通性通过WS-I(基本档)或WS-*标准性保证。
WCF中使用BasicHttpBinding支持WS-I基本档。
增加WS-*可以提高QOS,包括提高二进制数据传输效率(MTOM),安全性传输(WS-Security等),可靠性传输(WS-ReliableMessaging)