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

在双工系统中,WCF如何区分不同的通道实例?,wcf,Wcf,嗯,我完全迷路了,所以任何帮助都将不胜感激 OperationContext.Current.InstanceContext 是当前服务的上下文 实例,输入通道是 使用 在双工系统中,服务可以 通过 回拨合同。这 CallbackContract很像一个 客户端上的服务,即 正在侦听来自服务的呼叫 在客户端拥有的通道上 开的。这是“客户端回调” “服务”只能通过 与服务上使用的频道相同 因此,只有该服务具有 访问它 a) 因此,在双工系统中,客户端向服务发送消息的同一通道实例也被客户端用于从服

嗯,我完全迷路了,所以任何帮助都将不胜感激

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

在双工系统中,服务可以 通过 回拨合同。这 CallbackContract很像一个 客户端上的服务,即 正在侦听来自服务的呼叫 在客户端拥有的通道上 开的。这是“客户端回调” “服务”只能通过 与服务上使用的频道相同 因此,只有该服务具有 访问它

a) 因此,在双工系统中,客户端向服务发送消息的同一通道实例也被客户端用于从服务接收消息

b) 如果在请求-应答系统中,客户机使用特定的通道实例
clientChannel
向服务发送消息,那么我假设同一个实例(因此
clientChannel
)需要保持打开状态,直到服务将应答发送回该实例,在双工系统中,客户端通道是否需要保持打开状态,直到会话关闭

c) 我假设这样的行为,因为据我所知,每个通道实例都有一个唯一的地址(或ID),这有助于将它与其他通道实例区分开来)在同一个客户机上运行?当服务发回一条消息时,它还指定了这个通道的ID

因此,当在双工系统中客户端调用服务时,WCF(在客户端)创建一个通道实例
clientChannel
,该实例通过线路发送消息。在服务器端,WCF创建通道实例
serverChannel
,将消息传递给请求的操作(方法)。当此方法希望通过
CallbackContract
回调客户端时,它使用
InstanceContext.GetCallBackChannel
创建一个频道,其中包含调用服务的频道的ID(因此它包含
clientChannel
的确切地址或ID)

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


谢谢

我不确定,但以下是我对双工模式通信的理解。

我使用dotPeek反编译器查看了System.ServiceModel程序集中定义的InstanceContext类

内部有一个电话

this.channels = new ServiceChannelManager(this);
这意味着,它正在使用ServiceChannelManager创建通道,并传入同一InstanceContext的实例。 这样,它就可以通过InstanceContext实例跟踪频道

然后,is将传入通道(服务到客户端)请求绑定到方法中,该方法实现为:

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;
      }
    }
[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>();
        }
    }
}
因此,要回答您的问题:

a。是的,它在内部维护服务和InstanceContext(创建通道)的关系 客户端和服务之间的调用

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

c。每个客户端都有一个唯一的会话Id,但服务的InstanceContext类型取决于InstanceContextMode 用于服务合同的执行

d。它使用相同的频道。InstanceContext维护输入通道和输出通道的计数。 传入通道是服务到客户机导向的通道,传出通道是客户机到服务导向的通道。 您可以在VS中使用调试器查看此计数

为了进一步澄清,就双工服务的其他行为而言,以下是我们如何查看InstanceContext的行为以及如何创建通道实例:

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

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IServiceDuplexCallback))]
public interface IServiceClass
{
    [OperationContract(IsOneWay = true)]
    void Add(int num1);
}
本合同执行如下:

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;
      }
    }
[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>();
        }
    }
}
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:urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe545-urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe545

客户端2:urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f015-urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f015

此处-urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54为会话ID

因为对于每个客户机,Add在客户机中被调用两次,并且在PerCall->newinstanceContext中,每次调用都会创建InstanceContext实例,所以我们为每个客户机的两次调用都创建一个新的ServiceClass实例。这里需要注意的一点是,即使为同一个会话也会创建新实例

//第一次调用添加合同的方法

客户。添加(val1)->已创建ServiceClass的新实例,其值将增加到5

//第二次调用添加合同的方法

客户。添加(val2)->已创建ServiceClass的新实例,其值将增加到5

2-持续时间

客户1:urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe545-urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe5410

客户端2:urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f015-urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f0110

这里,ServiceClass的实例对于客户端和客户端都是独立的,因为它们运行着不同的会话。因此,调用的增量为0->5->10(分别针对两个客户端)

3-单曲

客户1:urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe545-urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54