WCF 回调原理

来源:互联网 发布:网络教育的考试 编辑:程序博客网 时间:2024/06/13 00:56

WCF回调操作简单的说就是由服务端来调用客户端的方法,回调时原先的服务端和客户端将发生对调,服务端成为客户端,客户端成为服务端。

WCF <wbr>回调原理

 在回调操作模式中,客户端对服务端调用实际上进行了四次通信

ServiceRequest:客户端向服务端发出调用,在调用的过程中会把回调实例的引用一起发送到服务端。

CallbackRequest:服务端从上一步的请求中取得对回调实例的引用,通过该回调实例向客户端发出的回调请求。

CallbackResponse:客户端执行完回调后向服务端返回的响应,如果回调契约中的方法契约被定义为IsOnWay的话,这一步不会发生。

ServiceResponse:服务端方法执行完后向客户端返回信息(方法的返回值等)。

1、WCF回调的必要条件:并不是所有的绑定都支持回调操作,只有具有双向通信能力的绑定才可以使用回调。比如HTTP是与连接无关的因此不能用于回调。这就说明我们不能使用BasicHttpBinding或WSHttpBinding进行回调。WCF中NetTcpBinding和NetNamedPipeBinding支持回调,因为从本质上讲TCP和IPC协议支持双向通信。WCF中wsDualHttpBinding也是支持回调的因为它实际上是设置了两个HTTP通道

2、定义回调契约

     回调契约是服务端定义客户端回调类的规范,客户端需要根据此契约生成回调类,服务端就通过此契约来调用客户端的相应方法。回调方法是在客户端执行的,而回调契约是定义在服务端,它规定客户端回调类的实现契约。一个服务契约若要定义回调,必须专门定义一个用于回调的契约。一个服务契约最多包含一个回调契约,一个服务契约一旦定义了回调契约那客户端必须支持这个回调。那如何为一个服务契约定义回调呢?使用ServiceContract特性的CallBackContract特性,代码如下

[ServiceContract(CallbackContract =typeof(ISomeCallbackContract))]
 public interface IService1
 {
 [OperationContract(IsOneWay=true)]
  void DoSomething();
 }
  //用于回调的契约
  interface ISomeCallbackContract
 {
    [OperationContract(IsOneWay=true)]
    void SomeCallbackMethod();
    [OperationContract(IsOneWay = true)]
    void SomeCallbackMethod2();

}

3、客户端回调设置

 客户端需要实现服务端定义的那个用于回调的契约ISomeCallbackContract,然后实例化回调对象再通过它创建一个上下文对象InstanceContext。然后用代理把这个回调的引用传回服务端

4、下面通过代码实例说明:

服务端代码

[ServiceContract(CallbackContract =typeof(ISomeCallbackContract))]
public interface IService1
{
 [OperationContract(IsOneWay=true)]
void DoSomething();
 }
//用于回调的契约,这里可以不用再申明ServiceContract,因为上面用了CallBackContract自然就申明了
 interface ISomeCallbackContract
{
 [OperationContract(IsOneWay=true)]
 void SomeCallbackMethod();
 [OperationContract(IsOneWay = true)]
void SomeCallbackMethod2();

}

实现服务的类:

[ServiceBehavior(InstanceContextMode =InstanceContextMode.PerSession, ConcurrencyMode =ConcurrencyMode.Reentrant)]
    public class Service1 : IService1
    {
        static List m_Callbacks = new List();
        public void DoSomething()
        {
             //获得由客户端传入的回调终结点的引用,使用这个引用可以调用客户端方法
             ISomeCallbackContract callback =OperationContext.Current.GetCallbackChannel();
            if (m_Callbacks.Contains(callback) == false)
            {
                m_Callbacks.Add(callback);
            }
            Trace.WriteLine("DoSomething");
             //调用客户端实现的SomeCallbackMethod2方法,
             callback.SomeCallbackMethod2();
            CallClients();
        }
 
        static public void CallClients()
       {
            Action invoke = delegate(ISomeCallbackContract callback)
            {
                callback.SomeCallbackMethod();
            };
            m_Callbacks.ForEach(invoke);
        }
     }

客户端代码:

 //客户端实现回调接口,使用VS自动生成代理的时候,对于回调接口的命名默认是以服务契约接口名称+Callback,而不是原先在服务端定义的回调接口的名子 
        public class CallBack :ServiceReferenceCallBack.IService1Callback
       {
            public void SomeCallbackMethod()
            {

                MessageBox.Show("SomeCallbackMethod()", "MyClient");
           }

            public void SomeCallbackMethod2()
            {
                MessageBox.Show("SomeCallbackMethod2()", "MyClient");
            }
        }

客户端调用

  首先生成回调接口实现的对象,然后用这个对象去实例化一个上下文对象context,在创建客户端代理对象的时候在构造方法中使用这个上下文对象context就可以把客户端回调对象的引用作为消息的一部分传送到服务端,在服务端就可以通过

OperationContext.Current.GetCallbackChannel()来获得这个回调对象的引用,服务端有了这个回调对象的引用就可以去调用客户端实现的回调方法

ServiceReferenceCallBack.IService1Callback callback = newCallBack();
InstanceContext context = new InstanceContext(callback);
ServiceReferenceCallBack.Service1Client sc = newWCFPrograme.ServiceReferenceCallBack.Service1Client(context);

sc.DoSomething();

 总结:

1、必须使用支持双向通信的绑定如NetTcpBinding、NetNamedPipeBinding、WSDualHttpBinding

2、用 CallbackContract 为服务定义回调,回调的接口在服务端定义。

     例:[ServiceContract(CallbackContract =typeof(ISomeCallbackContract))]

3、服务端用OperationContext.Current.GetCallbackChannel()获取调用当前操作的客户端实例通道

      例:

ISomeCallbackContract callback =OperationContext.Current.GetCallbackChannel()

4、服务端获得客户端实例通道的对象以后就可以调用客户端方法

    例:callback.SomeCallbackMethod2();

5、客户端生成代理以后,由客户端去实现回调接口

     例:

     public class CallBack :ServiceReferenceCallBack.IService1Callback
     {
       //实现接口
      }

6、客户端创建回调的对象并生成操作调用的上下文并由客户端代理对象传回服务端

ServiceReferenceCallBack.IService1Callback callback = newCallBack();
InstanceContext context = new InstanceContext(callback);
 ServiceReferenceCallBack.Service1Client sc = newWCFPrograme.ServiceReferenceCallBack.Service1Client(context);
 sc.DoSomething();
配置文件:使用wsDualHttpBinding的时候,需要在客户端配置文件中需要指定客户端基址clientBaseAddress,服务可以通过这个地址与客户

端取得联系,这是因为wsDualHttpBinding需要两条http通道,而是使用netTcpBinding时不需要

http://localhost:8731/Design_Time_Addresses/WcfCallBack/Service1/"
 binding="wsDualHttpBinding"bindingConfiguration="WSDualHttpBinding_IService1"
 contract="ServiceReferenceCallBack.IService1"name="WSDualHttpBinding_IService1">
 
      
 
 
 
 
 openTimeout="00:01:00" receiveTimeout="00:10:00"sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false"hostNameComparisonMode="StrongWildcard"
                  maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                   messageEncoding="Text" textEncoding="utf-8"useDefaultWebProxy="true" 
                       clientBaseAddress="
http://localhost:8008">
               
                     maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
                 
                   
                     
                            algorithmSuite="Default" />
                
              
           

 

转自:http://zzyman.blog.163.com/blog/static/1754101032012619114258100/

0 0
原创粉丝点击