WCF服务创建与使用(双工模式)

昨天发布了《WCF服务创建与使用(请求应答模式)》,今天继续学习与强化在双工模式下WCF服务创建与使用,步骤与代码如下。

第一步,定义服务契约(Service Contract),注意ServiceContract特性上需指定回调契约

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//服务契约
using  System.ServiceModel;
 
namespace  WcfServiceLibrary1
{
     [ServiceContract(Namespace = "http://www.zuowenjun.cn" ,
      CallbackContract = typeof (ICallback))]
     public  interface  IHello
     {
         [OperationContract(IsOneWay = true )]
         void  SetName( string  name);
     }
}
 
//回调契约(由于回调契约本质也是一个服务契约,所以定义方式和一般意义上的服务契约基本一样。
//有一点不同的是,由于定义服务契约时候已经通过[ServiceContract(CallbackContract=typeof(ICallback))]指明ICallback是一个服务契约了,所以ICallback不再需要添加ServiceContractAttribute特性)
using  System.ServiceModel;
 
namespace  WcfServiceLibrary1
{
     public  interface  ICallback
     {
         [OperationContract(IsOneWay = true )]
         void  ShowHello( string  name);
     }
}

第二步,实现服务契约,这里通过OperationContext.Current.GetCallbackChannel()获取回调契约

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using  System.ServiceModel;
 
namespace  WcfServiceLibrary1
{
     [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
     public  class  HelloService:IHello
     {
         public  void  SetName( string  name)
         {
             ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
             callback.ShowHello(name);
         }
     }
}

注意:ConcurrencyMode = ConcurrencyMode.Reentrant是设置并发模式,Reentrant与Multiple均可适用于多并发,默认是Single

第三步,创建服务寄宿程序,方法很多,我这里采取常用的配置方法

1.CONFIG文件配置部份:

(注: 1.在WCF预定义绑定类型中,WSDualHttpBinding和NetTcpBinding均提供了对双工通信的支持,但是两者在对双工通信的实现机制上却有本质的区别。WSDualHttpBinding是基于HTTP传输协议的;而HTTP协议本身是基于请求-回复的传输协议,基于HTTP的通道本质上都是单向的。WSDualHttpBinding实际上创建了两个通道,一个用于客户端向服务端的通信,而另一个则用于服务端到客户端的通信,从而间接地提供了双工通信的实现。而NetTcpBinding完全基于支持双工通信的TCP协议。
2.若绑定类型采用NetTcpBinding,则地址应变更为:net.tcp://127.0.0.1:10800/HelloService,且不能有behaviorConfiguration配置

1
2
3
4
5
6
7
8
9
10
11
<? xml  version="1.0" encoding="utf-8" ?>
< configuration >
   < system.serviceModel >
     < services >
       </ service >
       < service  name="WcfServiceLibrary1.HelloService">
         < endpoint  address="http://127.0.0.1:10800/HelloService" binding="wsDualHttpBinding" contract="WcfServiceLibrary1.IHello"></ endpoint >
       </ service >
     </ services >
   </ system.serviceModel >
</ configuration >

2.代码部份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using  System;
using  WcfServiceLibrary1;
using  System.ServiceModel;
using  System.ServiceModel.Description;
 
 
namespace  ConsoleApplicationHost
{
     class  Program
     {
         static  void  Main( string [] args)
         {
             BuildHelloServiceHostByConfig();
         }
 
         static  void  BuildHelloServiceHostByConfig()
         {
             using  (ServiceHost host = new  ServiceHost( typeof (HelloService)))
             {
                 host.Opened += (s, e) => { Console.WriteLine( "HelloService已经启动,按按回车键终止服务!" ); };
                 host.Open();
                 Console.ReadLine();
             }
         }
     }
}

第四步,客户端程序调用WCF服务

注:在客户端程序中首先需要创建或引用WCF服务类库,然后创建实现回调契约的类

实现回调契约:

1
2
3
4
5
6
7
8
9
10
11
12
13
using  System;
using  WcfServiceLibrary1;
 
namespace  ConsoleApplicationClient
{
     public  class  HelloCallBack:ICallback
     {
         public  void  ShowHello( string  name)
         {
             Console.WriteLine( "Hello! {0}.欢迎光临IT文俊社区网,地址:www.zuowenjun.cn" ,name);
         }
     }
}

1.CONFIG文件配置部份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<? xml  version="1.0" encoding="utf-8" ?>
< configuration >
     < system.serviceModel >
         < bindings >
           < wsDualHttpBinding >
             < binding  name="HelloServiceBinding" clientBaseAddress="http://127.0.0.1:10801/HelloServiceCallback"></ binding >
           </ wsDualHttpBinding >
         </ bindings >
         < client >
           < endpoint  name="HelloService" address="http://127.0.0.1:10800/HelloService" binding="wsDualHttpBinding" contract="WcfServiceLibrary1.IHello">
           </ endpoint >
         </ client >
     </ system.serviceModel >
</ configuration >

2.代码部份:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using  System;
using  System.ServiceModel;
using  WcfServiceLibrary1;
 
namespace  ConsoleApplicationClient
{
     class  Program
     {
         static  void  Main( string [] args)
         {
             CallHelloService();
             Console.WriteLine( "按任意键结束。" );
             Console.Read();
         }
 
         static  void  CallHelloService()
         {
             Console.Write( "请输入您的网名:" );
             string  input = Console.ReadLine();
             InstanceContext instanceContext = new  InstanceContext( new  HelloCallBack());
             using  (DuplexChannelFactory<IHello> channel = new  DuplexChannelFactory<IHello>(instanceContext, "HelloService" ))
             {
                 IHello proxy = channel.CreateChannel();
                 using  (proxy as  IDisposable)
                 {
                     proxy.SetName(input);
                     Console.ReadLine(); //注意这句需保留,目的是为了阻止调用proxy的Dispose方法,因为该方法将会试图关闭底层的TCP连接。由于服务端的回调操作也会使用该TCP连接,如果在回调操作尚未执行完毕就试图关闭网络连接,将会导致回调无法正常执行
                 }
             }
         }
     }
}

 

这里特别说明一下,建议在定义服务方法时,若没有返回值,建议为方法添加IsOneWay=True特性,可以使客户端不用等待请求回复,虽然设置ConcurrencyMode = ConcurrencyMode.Reentrant,但若采用WINFORM客户端使用,则会出现TIMEOUT错误,具体分析与解决方法,详见:我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案

说明:发表这篇文章参考了如下作者的文章:

我的WCF之旅(3):在WCF中实现双工通信

 

文章同步发表于我的个人网站:http://www.zuowenjun.cn/post/2015/03/25/133.html

本文转自 梦在旅途 博客园博客,原文链接:http://www.cnblogs.com/zuowj/p/4366939.html  ,如需转载请自行联系原作者

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值