博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WCF服务创建与使用(双工模式)
阅读量:6867 次
发布时间:2019-06-26

本文共 4619 字,大约阅读时间需要 15 分钟。

昨天发布了《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错误,具体分析与解决方法,详见:

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

 

文章同步发表于我的个人网站:

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

你可能感兴趣的文章
今天无意中发现的WWW.threadPriority
查看>>
js23---工厂模式1
查看>>
[转] Asp.Net 导出 Excel 数据的9种方案
查看>>
如何在Linux中用命令行工具管理KVM虚拟环境
查看>>
CSS 的优先级机制[总结]
查看>>
保证一个类仅有一个实例:单例模式
查看>>
JVM-ClassLoader装载class的流程
查看>>
redis实现分布式锁——核心 setx+pipe watch监控key变化-事务
查看>>
android 50 进程优先级
查看>>
软件设计之多边形区域内找点
查看>>
Medoo个人修改版
查看>>
Linux 上使用 Gmail SMTP 服务器发送邮件通知
查看>>
Linux下的定时任务Crontab
查看>>
动态规划之矩阵连乘问题
查看>>
电视剧《奋斗》能叫奋斗吗?
查看>>
关于在Windows Mobile下今日插件使用WTL的问题
查看>>
不用第三方之C#实现大容量报表系统
查看>>
[翻译]ADO.NET Entity Framework Beta2(三)/实体框架入门
查看>>
LoadRunner的那些事--lr11+IE8录制就崩溃卡死,firefox录制正常的解决方案
查看>>
JVM垃圾回收(GC)整理总结学习
查看>>