Как в дуплексной системе WCF различают разные экземпляры канала? - PullRequest
9 голосов
/ 27 октября 2010

Хм, я совершенно потерян, поэтому любая помощь будет высоко ценится

OperationContext.Current.InstanceContext - это контекст текущего экземпляра службы, который использует входящий канал.

В дуплексной системе служба может перезвонить клиенту через CallbackContract.Этот CallbackContract очень похож на службу на стороне клиента, которая прослушивает вызовы от службы на канале, который открыл клиент.Доступ к этой «службе обратного вызова клиента» возможен только через тот же канал, который использовался в службе, и, следовательно, только эта служба имеет к ней доступ.

a) То есть в дуплексных системах тот же экземпляр канала, с которымна стороне клиента отправляет сообщения в службу, также используется клиентом для получения сообщений от службы?

b) Если в системе запрос-ответ клиент использует конкретный экземпляр канала clientChannel для отправки сообщения в службу, то я предполагаю, что этот же экземпляр (таким образом * clientChannel) должен оставаться открытым, пока служба не отправитобратно ответ на этот экземпляр, в то время как в дуплексной системе clientChannel необходимо оставаться открытым до закрытия сеанса?

c) Я предполагаю такое поведение, поскольку, насколько я могу судить, каждый экземпляр канала имеетуникальный адрес (или идентификатор), который помогает отличить его от других экземпляров канала), работающий на том же клиенте?А когда служба отправляет обратно сообщение, оно также указывает идентификатор этого канала?

Таким образом, когда в системе Duplex клиент вызывает службу, WCF создает (на стороне клиента) экземпляр канала clientChannel, который отправляет сообщение по сети.На стороне сервера WCF создает экземпляр канала serverChannel, который доставляет сообщение в запрошенную операцию (метод).Когда этот метод хочет выполнить обратный вызов к клиенту через CallbackContract, он использует InstanceContext.GetCallBackChannel<> для создания канала, который среди прочего содержит идентификатор канала, который вызвал службу (таким образом, он содержит точный адрес или идентификатор * 1022).*)?

d) Использует ли клиент в дуплексных системах один и тот же экземпляр канала для вызова какой-либо из операций конечной точки?

Спасибо

1 Ответ

6 голосов
/ 10 февраля 2013

Я не уверен, но вот как я понимаю это для связи в дуплексном режиме.

Я посмотрел на класс InstanceContext, определенный в сборке System.ServiceModel, используя декомпилятор dotPeek.

Внутренний вызов

this.channels = new ServiceChannelManager(this);

Это означает, что он создает канал с использованием ServiceChannelManager, передавая экземпляр того же InstanceContext.Таким образом, он отслеживает канал с экземпляром InstanceContext.

Затем связывает входящие запросы канала (службы к клиенту) в методе, который реализован как:

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;
      }
    }

ответьте на ваши вопросы:

a.Да, он поддерживает отношения Service и InstanceContext (который создает канал) для вызовов между Клиентом и Сервисом.

b.Да, канал должен оставаться открытым, пока Сервис не ответит обратно в контекст, в котором InstanceContext позаботится о закрытии канала.

c.Каждый клиент имеет уникальный идентификатор сеанса, но тип InstanceContext в Сервисе зависит от InstanceContextMode, используемого в Сервисе при реализации Договора.

d.Он использует тот же канал.InstanceContext поддерживает количество входящего канала и исходящего канала.Входящий канал - это канал, ориентированный на обслуживание к клиенту, а исходящий канал направлен на обслуживание от клиента.Вы можете увидеть это количество, используя отладчик в 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>();
        }
    }
}

В этой реализации обратите внимание на первую строку, где InstanceContextModeустановлен на PerCall. По умолчанию используется PerSession.

Это перечисление имеет три параметра:

  1. PerCall - новый экземпляр InstanceContext, используемый для каждого вызова, независимого от Session

  2. PerSession - новый экземпляр, используемый для каждого сеанса

  3. Single - один экземпляр 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();
    }
}

ToПосмотрите поведение InstanceContext, я запустил службу, а затем запустил двух клиентов с каждой операцией перечисления, как обсуждалось выше.Вот результаты:

1 - PerCall

Клиент 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5 -urn: 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 для обоих вызовов каждого клиента.Следует отметить, что новый экземпляр создается даже для того же сеанса

// Первый вызов метода Add контракта

client.Add (val1); -> Создан новый экземпляр ServiceClass, и значение будет увеличено до 5

// Второй вызов метода Add контракта

client.Add (val2); -> Создан новый экземпляр ServiceClass, и значение будет увеличено до 5

2 - PerSession

Клиент 1: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5 - urn: 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: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5 - urn: 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: urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 5 - urn: uuid: 4c5f3d8b-9203-4f25-b09a-839089ecbe54 15

Клиент 2: urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 10 - urn: uuid: e101d2a7-ae41-4929-9789-6d43abf97f01 20

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...