zoukankan      html  css  js  c++  java
  • 在wcf中实现双工通信

    读wcf全面解析之笔记
    如果按照双工模式(Duplex)进行消息交换,则已意味着参与消息交换的双方都能勾向对方发送消息,双工通信不仅仅使服务回调客户端成为可能,还可以帮助我们实现基于发布-订阅的方式进行通信。

    服务回调客户端:客户端在进行服务调用的时候,附加上一个回调对象。服务在执行服务操作的过程中,通过回调这个对象来回调客户端的操作。
    发布-订阅的方式:其实是一中双工模式的典型变体,这个有点类似在C#中的委托和事件、也有点类似设计模式中的观察者模式。
    具体的就是说若干的订阅者就某个主题向发布者申请订阅,发布者将所有订阅者保存在一个订阅者列表,在某个时刻将主体发送给该主题的订阅者。

    接下来通过一个简单的实例来演示回调在wcf中的应用
    1.建一个空的解决方案,然后添加4个项目:
    ①Client控制台应用程序,最为客户端来显示回调结果
    ②ServerHosting控制台应用程序,服务的宿主程序,用来寄宿服务的。
    ③Services类库,用来创建服务。
    ④Contracts类库,用来创建服务契约
    2.建立完成之后开始来定义契约
    ①在Contracts项目上建立一个契约接口ICalculator,通过回调方式在客户端输出运算结果,所以Add并无返回值。
    using System.ServiceModel;
    [ServiceContract(Namespace="http://www.lordbaby.com",
            CallbackContract=typeof(ICalculatorCallback))]
        public interface ICalculator
        {
            [OperationContract]
            void Add(double x,double y);
        }


    服务对客户端进行回调相当于调用寄宿于客户端的"回调服务",所以需要确定回调的服务契约,这个契约通过应用在契约接口ServiceContractAttribute特性的CallbackContract属性来指定。然后就是回调契约的接口定义如下:
    using System.ServiceModel;
    public interface ICalculatorCallback
        {
            [OperationContract]
            void DisplayResult(double result, double x, double y);
        }


    ②在Services项目中建立实现了契约接口ICalculator的服务CalculatorService,定义如下
    [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
        public class CalculatorService:ICalculator
        {
            public void Add(double x, double y)
            {
                double result = x + y;
                ICalculatorCallback callback = OperationContext.Current.GetCallbackChannel<ICalculatorCallback>();
                callback.DisplayResult(result, x, y);
            }
        }


    通过当前服务操作的上下文调用GetCallbackChannel<T>(T为回调契约类型)得到用于调用回调服务的对象,最终通过回调代理的DisplayResult
    注:OperationContext是wcf十分重要的对象,它代表服务操作执行的上下文,可以通过OperationContext.Current来得到当前的OperationContext,比如在客户端可以通过它为出栈消息(outgoing message)添加SOAP报头,以及HTTP报头(比如Cookie)等。在服务端,则可以通过OperationContex获取在客户端设置的SOAP报头和HTTP报头。关于OperationContext的详细信息.
    ③在Client项目中定义实现可回调契约的“回调服务”来显示元算结果
    public class CalculatorCallbackService:ICalculatorCallback
        {
            public void DisplayResult(double result, double x, double y)
            {
                Console.WriteLine("x+y={2} when x={0},y={1}",x,y,result);
            }
        }

    然后建立一个客户端配置文件:
    <configuration>
      <system.serviceModel>
        <client>
          <endpoint name="calculatorservice"
                     address="net.tcp://127.0.0.1:9999/calculatorservice"
                     binding="netTcpBinding"
                     contract="Contracts.ICalculator"/>
        </client>
      </system.serviceModel>
    </configuration>
    ④在ServiceHosing项目中寄宿服务
    class Program
        {
            static void Main(string[] args)
            {
                using (ServiceHost host=new ServiceHost (typeof(CalculatorService)))
                {
                    host.Open();
                    Console.WriteLine("Calculator已经启动,按任意键结束");
                    Console.Read();
                }
            }
        }
    然后建立一个服务端配置文件
    <configuration>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="mybehavior">
              <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <services>
          <service name="Services.CalculatorService">
            <endpoint address="net.tcp://127.0.0.1:9999/calculatorservice"
                      binding="netTcpBinding"
                      contract="Contracts.ICalculator"/>
          </service>
        </services>
      </system.serviceModel>
    </configuration>
    ⑤在Client中回调服务
    static void Main(string[] args)
            {
                InstanceContext instanceContext = new InstanceContext(new CalculatorCallbackService());
                using (DuplexChannelFactory<ICalculator> channelFactory = new DuplexChannelFactory<ICalculator>(instanceContext, "calculatorservice"))
                {
                    ICalculator proxy = channelFactory.CreateChannel();
                    using (proxy as IDisposable)
                    {
                        proxy.Add(1, 2);
                        Console.Read();
                    }
                }
            }
    注意:1.服务代理工厂换成了DuplexChannelFactory<TChannel>
    2.调用之前需要指定一个用于封装回调对象的InstanceContext
    好了现在可以运行程序,分别用2个vs打开解决方案,首先设ServiceHosting项目启动项目,运行


    然后在另一个vs中设Client为启动项目,运行,输出结果:

            
    注:如果没有在Services项目中的CalculatorService中

    源码:wcfDuplexDemo

  • 相关阅读:
    移动布局之弹性布局
    .dpg和.webp的图片格式
    跳转不到对应的JSP页面
    CentOS7配置vsftpd3.0.2
    Linux如何将用户从一个组中移除?
    数组和方法
    运算符
    数据类型转换
    Apache的虚拟主机配置及伪静态操作
    Linux--文件的上传和下载
  • 原文地址:https://www.cnblogs.com/hailiang2013/p/2846421.html
Copyright © 2011-2022 走看看