双工系统WCF如何区分不同的通道实例?

问题描述:

嗯,我完全失去了任何帮助,将不胜感激双工系统WCF如何区分不同的通道实例?

的 OperationContext.Current.InstanceContext 是当前服务 实例的背景下,输入通道是 使用。

在双工系统中,该服务可以通过 CallbackContract向客户端回拨 。此 CallbackContract非常类似于客户端上的 服务,即 正在侦听客户端打开的客户端的服务 上的呼叫 。这种“客户端回调 服务”只能通过它的服务 使用的 相同的信道进行访问,因此仅该服务具有 访问它。

a)因此,在双工系统中,客户端向服务发送消息的同一个通道实例也被客户端用于接收来自服务的消息? b)如果在请求 - 回复系统中客户端使用特定的信道实例clientChannel向服务发送消息,那么我假设这个相同的实例(因此clientChannel)需要保持打开状态,直到服务发送回应给这个实例,而双工系统clientChannel需要保持打开状态直到会话关闭?

三)我假设这样的行为,因为据我可以告诉每个通道实例都有一个唯一的地址(或ID),这有助于从其他渠道情况区别开来)在同一客户端上运行?当服务发回消息时,它还指定了此频道的ID?

因此,当在双面打印系统客户端调用服务,WCF创建(在客户侧)的信道实例clientChannel,其通过线路发送消息。在服务器端,WCF创建通道实例serverChannel,它将消息传递到请求的操作(方法)。当这种方法想要经由CallbackContract回调到客户端,它使用InstanceContext.GetCallBackChannel<>创建一个信道,这除其它外包含称为服务信道的ID(因此它包含的clientChannel一个确切的地址或ID)?

d)在双工系统客户端是否使用同一个通道实例调用任何端点的操作?

谢谢

+0

我读过一些可以澄清一点的东西,但仍然给出了关于双绑定伏都教的一些答案:TCP和命名管道传输协议隐含地支持回调。他们总是可以回到客户端。对于HTTP,DuplexClientBase 通过在客户端上托管服务并在端口80上侦听来自服务的消息的临时http地址来处理客户端端点的创建。 – Trevor 2013-02-07 10:18:57

我不知道,但这里是我的理解这一个双工模式通信。

我看了一下使用反编译dotPeek的System.ServiceModel集中定义的类的InstanceContext。

在内部有一个呼叫

this.channels = new ServiceChannelManager(this); 

这意味着,它使用的是ServiceChannelManager通过在相同的InstanceContext的实例创建信道。 这样,它通过InstanceContext的实例来跟踪Channel。

则结合输入通道(服务于客户端),它为实现在方法请求:

internal void BindIncomingChannel(ServiceChannel channel) 
    { 
     this.ThrowIfDisposed(); 
     channel.InstanceContext = this; 
     IChannel channel1 = (IChannel) channel.Proxy; 
     this.channels.AddIncomingChannel(channel1); 
     if (channel1 == null) 
     return; 
     switch (channel.State) 
     { 
     case CommunicationState.Closing: 
     case CommunicationState.Closed: 
     case CommunicationState.Faulted: 
      this.channels.RemoveChannel(channel1); 
      break; 
     } 
    } 

因此,要回答您的疑问:

一个。是的,它在内部维护Client和Service之间的 调用的Service和InstanceContext(它创建一个通道)关系。

b。是的,频道需要保持打开状态,直到服务回复到上下文,其中InstanceContext 将负责关闭频道。

c。每个客户端都有一个唯一的会话ID,但服务上的InstanceContext类型取决于服务在实施合同时使用的InstanceContextMode 。 d)。它使用相同的频道。 InstanceContext维护IncomingChannel和Outgoing频道的计数。 传入通道是指向服务的客户端和传出的客户端到服务的对象。 您可以在VS中使用调试器来查看此计数。

为了进一步澄清起见,尽可能为双工服务的其他行为来看,这里是我们如何看待的InstanceContext的行为,以及如何通道实例被创建:

我创建了一个双工服务演示:

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IServiceDuplexCallback))] 
public interface IServiceClass 
{ 
    [OperationContract(IsOneWay = true)] 
    void Add(int num1); 
} 

本合同为执行:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] 
public class ServiceClass : IServiceClass 
{ 
    int result = 0; 

    public void Add(int num1) 
    { 
     result += num1; 
     callBack.Calculate(result); 
    } 

    IServiceDuplexCallback callBack 
    { 
     get 
     { 
      return OperationContext.Current.GetCallbackChannel<IServiceDuplexCallback>(); 
     } 
    } 
} 

在此实现注意到的第一行,其中InstanceConte xtMode被设置为PerCall。 默认是PerSession。

此枚举有三个选项:

  1. PerCall - 的InstanceContext的新实例用于每个呼叫无关的会议

  2. PerSession - 新的实例用于每个会话

  3. 单 - 用于所有客户端的InstanceContext的单个实例。

我创建了使用NetTcpBinding的与服务连接的客户端:

InstanceContext ic = new InstanceContext(new TCPCallbackHandler(ref textBox1)); 
TCP.ServiceClassClient client = new TCP.ServiceClassClient(ic); 

// First call to Add method of the Contract 
client.Add(val1); 
// Second call to Add method of the Contract 
client.Add(val2); 

TCPCallbackHandler是实现回调合同的客户端类:

public class TCPCallbackHandler : TCP.IServiceClassCallback 
{ 
    TextBox t; 

    public TCPCallbackHandler(ref TextBox t1) 
    { 
     t = t1; 
    } 

    public void Calculate(int result) 
    { 
     t.Text += OperationContext.Current.SessionId + " " + result.ToString(); 
    } 
} 

要查看InstanceContext的行为,我开始了服务,然后启动了两个客户端,每个枚举操作都使用 ,如上所述。下面是结果:

1 - PerCall

客户1:金塔:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54 - 瓮:UUID:4c5f3d8b-9203-4f25-b09a- 839089ecbe54

客户端2:瓮:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01 - 瓮:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01

这里 - 瓮:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54是SessionID的

由于每个客户端添加在客户端调用两次,并在PerCall - >的InstanceContext的新实例创建的每个呼叫,我们为每个客户端的调用创建一个新的ServiceClass实例。这里要注意的是,新的实例,即使是同一个会话

//第一次调用添加合同

client.Add(VAL1)的方法创建的; - >服务类的新实例创建和值将被递增到5

//第二呼叫添加合同的方法

client.Add(val2次); - >服务类的新实例创建和值将被递增到5

2 - PerSession

客户端1:瓮:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54 - 瓮:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54

客户端2:瓮:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01 - 瓮:UUID:e101d2a7-ae41-4929-9789 -6d43abf97f01

这里,ServiceClass的实例对客户端来说是分开的,因为它们有不同的会话在运行。因此,在呼叫的增量是0 - > 5 - > 10(为客户端分开)

3 - 单

客户端1:瓮:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54 - 瓮:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54

客户端2:瓮:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01 - 瓮:UUID:e101d2a7- ae41-4929-9789-6d43abf97f01

这里所有的客户端共享同一个ServiceClass实例,所以我们在第一个客户端有0 - > 5 - > 10。第二个客户端将在同一个实例中增加,所以我们得到10 - > 15 - > 20。

这将有不同的行为,根据调用,可能会给出像从客户端同时调用的结果。

客户端1:瓮:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54 - 瓮:UUID:4c5f3d8b-9203-4f25-b09a-839089ecbe54

客户端2:瓮:UUID :e101d2a7-ae41-4929-9789-6d43abf97f01 - 瓮:UUID:e101d2a7-ae41-4929-9789-6d43abf97f01

希望这有助于!