欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

WCF全双工通信实例分享(wsDualHttpBinding、netTcpBinding两种实现方式)

程序员文章站 2023-02-02 09:09:12
最近在研究WCF通信,如果没有接触过的可以看我的前一篇文章:https://www.cnblogs.com/xiaomengshan/p/11159266.html 主要讲的最基础的basicHttpBinding方式的单工WCF通信,步骤比较详细,所以本文就只说明关键的细节,详细的步骤操作可以参考 ......

  最近在研究wcf通信,如果没有接触过的可以看我的前一篇文章:https://www.cnblogs.com/xiaomengshan/p/11159266.html 主要讲的最基础的basichttpbinding方式的单工wcf通信,步骤比较详细,所以本文就只说明关键的细节,详细的步骤操作可以参考前一篇文章,还望理解。本文使用的环境是vs2015,使用的项目都是wpf,如使用winform、web项目的可能有些细微的差别,不过原理应该差不多,各位可以自己调试一下。
  全双工的方式主要是依靠回调客户端函数的方式实现,可以构造数据包处理接口来实现常规c/s架构,也可以搭建发布/订阅机制的系统,看具体使用了。平时新建的wcf服务默认是basichttpbinding方式的单工方式,支持全双工的有wsdualhttpbinding、nettcpbinding及mexnamedpipebinding。wsdualhttpbinding通过建立两条http协议的方式实现全双工;nettcpbinding使用的net.tcp协议进行通信;mexnamedpipebinding采用net.pipe的方式,但是该方式好像只支持同一系统间不同进程的通信。当然还支持很多其他的方式,不过每去研究。本文只分享wsdualhttpbinding、nettcpbinding方式的通信案例,因为其他的我自己没实际测试过,不敢误导大家。

 

wsdualhttpbinding实现全双工

一、服务器端

1、创建wcf服务

自动生成imywcfbothway.cs与mywcfbothway.cs

 

2、编写服务契约接口

1 [servicecontract(sessionmode = sessionmode.required, callbackcontract = typeof(icallback))] 
2     public interface imywcfbothway
3     {
4         [operationcontract]
5         string dowork(string msg);
6     }

 注:

1、callbackcontract = typeof(icallback))即为声明回调契约为icallback

2、[operationcontract]如不声明则客户端引用服务时对该接口函数不可见

 

3、编写回掉契约接口

 

1   public interface icallback
2     {
3         [operationcontract(isoneway = true)]
4         void clientcallback(string msg);
5     }

 

注:
1、[operationcontract(isoneway = true)] 声明单向后该接口函数不支持输出,即不能设置返回值和ref/out传入引用
2、该接口服务器端不需实现,但需要在客户端实现

4、实现服务契约接口

 

 1 public class mywcfbothway : imywcfbothway
 2     {       
 3         public string dowork(string msg)
 4         {
 5             string str = msg + "访问服务器成功";
 6             //获取客户端实现回调接口的子类实例
 7             icallback icallback = operationcontext.current.getcallbackchannel<icallback>();             
 8             console.writeline(msg+"访问服务器");
 9             console.writeline(msg + "服务器执行回调");   
10             //执行客户端的回调函数         
11             icallback.clientcallback("服务器执行回调成功");
12             console.read();
13             return str;
14         }
15     }

 

 

 

注:
1、如需回调客户端函数,需要使用operationcontext.current.getcallbackchannel<t> 获取客户端实现回调接口实例

 

5、修改配置文件

 

 1 <service name="wcfserver.mywcfbothway">
 2                 <endpoint address="" binding="wsdualhttpbinding" contract="wcfserver.imywcfbothway">
 3                     <identity>
 4                         <dns value="localhost" />
 5                     </identity>
 6                 </endpoint>
 7                 <endpoint address="mex" binding="mexhttpbinding" contract="imetadataexchange" />
 8                 <host>
 9                     <baseaddresses>
10                         <add baseaddress="http://localhost:8733/design_time_addresses/wcfserver/mywcfbothway/" />
11                     </baseaddresses>
12                 </host>
13             </service>
14 </services>



注:
1、主要修改使用的方式改为wsdualhttpbinding

2、http://localhost:8733/design_time_addresses/wcfserver/mywcfbothway/ 就为客户端服务引用的链接

3、本地测试可以使用localhost,如发布服务器需改为服务器ip

4、端口修改有时会报权限不足,可以将vs用管理员权限打开再编译

6、启动服务

1 servicehost host1 = new servicehost(typeof(wcfserver.mywcfbothway));
2 host1.open();

 

二、客户端

1、引用wcf服务

通过服务引用引用wcf服务:http://localhost:8733/design_time_addresses/wcfserver/mywcfbothway/

2、实现回调契约接口

1 [callbackbehavior(usesynchronizationcontext = false)]
2     public class myclientcallback: imywcfbothwaycallback
3     {
4         public void clientcallback(string msg)
5         {
6             console.writeline(msg);
7             console.read();
8         }
9     }
注:
1、实现的回调接口为imywcfbothwaycallback,而不是服务器声明的icallback,可以在引用服务后使用对象查看器查看,中间应该是经过代理把名称统一换了
2、需要声明[callbackbehavior(usesynchronizationcontext = false)],否则回调回失败,感觉像找不到回调函数还是阻塞了就超时了

 

3、访问wcf服务

 

 1 //声明回调实现类实例
 2 myclientcallback callback = new myclientcallback();
 3 //使用回调实现类实例创建会话实例
 4 instancecontext context = new instancecontext(callback);
 5 //创建wcf服务实例,传入会话实例给服务器是为了方便服务器通过该会话进行回调
 6 wcfbothway.mywcfbothwayclient w = new mywcfbothwayclient(context);
 7 //访问wcf服务
 8 string msg = w.dowork("客户端1");
 9 console.writeline(msg);
10 console.read();

 

 

 

nettcpbinding实现全双工

  其实nettcpbinding方式与wsdualhttpbinding方式用法基本相同,区别只是在一些配置上面,所以下面只说明其中的不同点就不一步步详细冗余说明了。

 

服务契约接口实现:

[servicebehavior(concurrencymode = concurrencymode.multiple)]
    public class wcfnettcp : iwcfnettcp
    {
        public string dowork(string msg)
        {
           console.writeline(msg + "访问服务器");
                console.read();
                //获取客户端实现回调接口的子类实例
                icallbacknettcp icallback = operationcontext.current.getcallbackchannel<icallbacknettcp>(); 
                icallback.callback("执行回调");               
                string str = msg + "访问服务器成功";
                return str;
        }
    }

注:这个要声明[servicebehavior(concurrencymode = concurrencymode.multiple)],不然会报错

 

app.config:

 1 <behaviors>
 2             <servicebehaviors>
 3                 <behavior name="">
 4                     <servicemetadata httpgetenabled="false" httpsgetenabled="false" />
 5                     <servicedebug includeexceptiondetailinfaults="false" />
 6                 </behavior>
 7             </servicebehaviors>
 8 </behaviors>
 9 
10 <service name="wcfserver.wcfnettcp">
11                 <endpoint address="" binding="nettcpbinding" contract="wcfserver.iwcfnettcp">
12                     <identity>
13                         <dns value="localhost" />
14                     </identity>
15                 </endpoint>
16                 <endpoint address="mex" binding="mextcpbinding" contract="imetadataexchange"/>
17                 <host>                  
18                     <baseaddresses>
19                         <add baseaddress="net.tcp://localhost:8732/design_time_addresses/wcfserver/wcfnettcp/" />
20                     </baseaddresses>
21                 </host>             
22 </service>  

主要修改的是配置文件:

1、servicemetadata httpgetenabled="false" httpsgetenabled="false" 可能是不使用http协议的原因,这两个选项要置为false

2、binding="nettcpbinding"要指定nettcpbinding方式

3、binding="mextcpbinding"指定使用tcp方式

4、net.tcp://localhost:8732/design_time_addresses/wcfserver/wcfnettcp/" 要将前缀声明为net.tcp协议

 

  其余部分的实现和wsdualhttpbinding方式基本相同~

 

 

  这次测试了这两种全双工方式的wcf通信,感觉wcf还是很强大方便的,但是还有很多参数不大清楚,只是使用的默认参数,还需继续去研究。