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

  • 相关阅读:
    matplotlib 进阶之origin and extent in imshow
    Momentum and NAG
    matplotlib 进阶之Tight Layout guide
    matplotlib 进阶之Constrained Layout Guide
    matplotlib 进阶之Customizing Figure Layouts Using GridSpec and Other Functions
    matplotlb 进阶之Styling with cycler
    matplotlib 进阶之Legend guide
    Django Admin Cookbook-10如何启用对计算字段的过滤
    Django Admin Cookbook-9如何启用对计算字段的排序
    Django Admin Cookbook-8如何在Django admin中优化查询
  • 原文地址:https://www.cnblogs.com/hailiang2013/p/2846421.html
Copyright © 2011-2022 走看看