wcf - 在双工系统WCF中如何区分不同的 channel 实例?

标签 wcf

嗯,我完全迷路了,因此不胜感激



OperationContext.Current.InstanceContext
是当前服务的上下文
传入通道是
使用。

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


a)因此,在双工系统中,客户端还将客户端用来向服务发送消息的相同通道实例用于接收来自服务的消息吗?

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

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

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

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

谢谢

最佳答案

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

我查看了使用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;
      }
    }


因此,回答您的问题:

一个。是的,它在内部维护Service和InstanceContext(创建通道)的关系
客户与服务之间的呼叫。

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

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

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

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

我创建了一个Duplex服务演示:

[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>();
        }
    }
}


在此实现中,请注意第一行,其中InstanceContextMode设置为PerCall。默认值为PerSession。

此枚举有三个选项:


PerCall-InstanceContext的新实例,用于与Session无关的每个调用
PerSession-用于每个会话的新实例
Single-用于所有客户端的InstanceContext的单个实例。


我创建了一个使用NetTcpBinding与Service连接的客户端:

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是客户端中的类,用于将Callback合同实现为:

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 5-缸:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 5

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

在这里-urn:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54是SessionId

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

//首次调用Contract的Add方法

client.Add(val1); ->创建的ServiceClass的新实例,值将增加到5

//第二次调用Contract的Add方法

client.Add(val2); ->创建的ServiceClass的新实例,值将增加到5

2-PerSession

客户1:缸:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 5-缸:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 10

客户2:urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 5-urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 10

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

3-单人

客户1:缸:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 5-缸:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 10

客户2:urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 15-urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 20

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

这与调用的行为不同,并且可能会像从客户端同时调用时那样产生结果。

客户1:缸:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 5-缸:uuid:4c5f3d8b-9203-4f25-b09a-839089ecbe54 15

客户2:urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 10-urn:uuid:e101d2a7-ae41-4929-9789-6d43abf97f01 20

希望这可以帮助!

关于wcf - 在双工系统WCF中如何区分不同的 channel 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4036488/

相关文章:

asp.net - 通过http将数据从服务器推送到浏览器

wcf - 如何使 WCF 服务使用特定的 DataContractSerializer 构造函数重载?

c# - 添加到 webmethods 的额外参数

web-services - 使用 WCF 使用 HTTPS Web 服务

wcf - 无法记录 WCF 消息正文

wcf - 通过环境变量动态指定 WCF 服务端点

wcf - 同一服务器内 WCF Web Services 的通信时间长

wcf - 使用 -Namespace 时 New-WebServiceProxy cmdlet 中存在错误?

c# - 无法正确引用 wcf 数据服务

.net - 使用不同的 X509 证书配置 WCF SOAP 请求/响应的加密和签名