zoukankan      html  css  js  c++  java
  • WCF服务编程契约回调

    双向通讯是这样的一种机制,就是服务端与客户端的身份是可换的,服务示例可以回调客户端的操作,当一个服务契约被定义在服务端的时候,有时候我们的业务逻辑要求我门进行相应的回调操作。标准的服务契约定义了能够被客户端调用的服务操作。回调契约定义了能够被服务端调用的客户端操作。因此,客户端必须具有实现回调契约的义务和宿主回调对象的能力。每当客户端调用具有回调操作的服务端示例操作的时候,客户端必须提供足够的信息以使服务端能够寻址到客户端并执行相应的回调操作。[引用]

    接下来我们就来做这样的一个场景,这个场景也是从网上看的。WCF服务端提供一个加法的服务,客户端调用服务端的服务之后,服务端回调客户端的显示方法最后将结果显示在客户端界面。下面是运行的效果,源码在此下载

    image

    在WCF的默认的绑定中WSDualHttpBinding是一个安全且可互操作的绑定。适用于双工服务协定或通过 SOAP 媒介进行的通信。本示例就是基于此绑定来实现的。为在编程中多应用些WCF编程的技术,服务端采用代码来创建服务端承载。

    第一步 创建标准契约和回调契约

    回调契约,用于在客户端显示结果信息 

    [ServiceContract(Namespace="http://www,cbcye.com/wcf/Callback/)]
    public interface ICalculatorCallback
    {
        [OperationContract]
        
    void ShowResult(double x, double y, double result);

    标准契约,声明了回调契约的类型 

    [ServiceContract(CallbackContract = typeof(ICalculatorCallback))]
    public interface IDuplexCalculator
    {
        [OperationContract]
        
    void Add(double x, double y);

    第二步 在服务端实现标准契约 

    [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
    public class DuplexCalculatorService:IDuplexCalculator


        
    IDuplexCalculator Members
    }
     

     

    第三步 创建服务端承载  

    class Program
        
    {
            
    static void Main(string[] args)
            
    {
                HostCalculatorService();
            }
     
            
    static void HostCalculatorService()
            
    {
                Uri dualUri 
    = new Uri("http://localhost:7788/cbcye/Calculator%22);
                //向HOST中添加BaseAddress
                using (ServiceHost calculatorServiceHost = new ServiceHost(typeof(DuplexCalculatorService), dualUri))
                
    {
                    
    //WSDualHttpBinding适用于双工服务协定或通过 SOAP 媒介进行的通信。
                    WSDualHttpBinding wsDualHttpBinding = new WSDualHttpBinding();
                    
    //添加服务绑定和服务契约
                    calculatorServiceHost.AddServiceEndpoint(typeof(IDuplexCalculator), wsDualHttpBinding, string.Empty); 

                    
    //绑定服务行为
                    ServiceMetadataBehavior behavior = calculatorServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    
    {
                        
    if (behavior == null)
                        
    {
                            behavior 
    = new ServiceMetadataBehavior();
                            behavior.HttpGetEnabled 
    = true;
                            calculatorServiceHost.Description.Behaviors.Add(behavior);
                        }

                        
    else
                        
    {
                            behavior.HttpGetEnabled 
    = true;
                        }

                    }
     

                    
    //启动事件
                    calculatorServiceHost.Opened += delegate
                    
    {
                        Console.WriteLine(
    "Calculator Service has begun to listen   on "+ dualUri.ToString());
                    }


                    calculatorServiceHost.Open();
                    Console.Read();
                }

            }

        }
     

     

    第四步 在客户端实现回调契约  

    class CalculatorCallbackHandler:ICalculatorCallback
    {
        
    #region ICalculatorCallback Members 

        
    public void ShowResult(double x, double y, double result)
        {
            Console.WriteLine(
    "x + y = {2} (x = {0} , y = {1})", x, y, result);
        } 

        
    #endregion

    第五步 实现客户端代理 

    class ClientProxy:ClientBase<IDuplexCalculator>,IDuplexCalculator


        
    public ClientProxy(InstanceContext callbackInstance)
           : 
    base(callbackInstance)
        { } 

        
    #region IDuplexCalculator Members 

        
    public void Add(double x, double y)
        {
            
    this.Channel.Add(x, y);
        }
        
    #endregion

    第六步 客户端调用

    程序代码

    class Program
    {
        
    static void Main(string[] args)
        
    {
            
    try
            
    {
                InvocateDuplexCalculator();
            }

            
    catch (Exception exp)
            
    {
                Console.WriteLine(
    "[Error] " + exp.Message);
            }
     

            Console.Read();
        }
     
        
    static void InvocateDuplexCalculator()
        
    {
            CalculatorCallbackHandler callbackHandler 
    = new CalculatorCallbackHandler(); 

            
    using (ClientProxy calculator = new ClientProxy(new InstanceContext(callbackHandler)))
            
    {
                Console.WriteLine(
    "Begin to invocate duplex calculator ");
                calculator.Add(
    8586);
                calculator.Close();
            }

        }

    }
     

    配置文件

    由于使用WSDualHttpBinding绑定执行回调时,需要开通两个HTTP通道,一个用于服务,一个用于回调。因此需要配置两个HTTP地址。 

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      
    <system.serviceModel>
        
    <client>
          
    <!--bindingConfiguration - 指定一个binding的配置名称,跟<bindings>下面同类<binding>的name匹配-->
          
    <endpoint name="SubscriptionService"
                          address
    ="http://localhost:7788/cbcye/Calculator%22
                          binding="
    wsDualHttpBinding"
                          bindingConfiguration
    ="wsDualHttpBinding_DuplexCalculator"
                          contract
    ="Cbcye.Contract.IDuplexCalculator"
                
    />
        
    </client>
        
    <bindings>
          
    <!-- 指定一个或多个系统预定义的binding,比如<basicHttpBinding>,当然也可以指定自定义的customBinding,
                 然后在某个指定的binding下建立一个或多个配置,以便被Endpoint来使用这些配置 
    -->
          
    <wsDualHttpBinding>
            
    <binding
                        
    name="wsDualHttpBinding_DuplexCalculator"
                        clientBaseAddress
    ="http://localhost:7799/cbcye/Calculator%22
              />
          </wsDualHttpBinding>
        </bindings>
      </system.serviceModel>
    </configuration> 
  • 相关阅读:
    Linux命令行和Shell脚本编程
    Excel自动触发时间
    dom4j读取xml文件 简单例子
    GSM & Foxit Reader
    ThreadPoolExecutor 线程池
    Linux /var/log
    delphi开发技巧
    利用ScktSrvr打造多功能Socket服务器
    delphi中Windows消息大全使用详解
    自己构造注入点方便入侵
  • 原文地址:https://www.cnblogs.com/cbcye/p/1495447.html
Copyright © 2011-2022 走看看