Как мы можем определить, когда клиент WCF отключился? - PullRequest
6 голосов
/ 08 июня 2011

Есть ли способ узнать, когда клиент WCF отключился. В настоящее время кажется, что единственный подход состоит в том, чтобы подождать, пока время ожидания вызова со стороны клиента из службы не истечет.

Я пытался подписаться на событие OperationContext.Current.Channel.Faults, но, к сожалению, оно никогда не вызывалось; Насколько я понимаю, это событие должно быть запущено, когда клиент исчезает. С другой стороны, когда все изящно закрывается, вызывается OperationContext.Current.Channel.Closed.

В нашем приложении мы поддерживаем только одно клиентское соединение за раз, поэтому, когда кто-то закрывает и перезапускает клиентское приложение, было бы неплохо, если бы сервер мог узнать об отключении, аккуратно привести в порядок, а затем принять другое соединение.

Да, клиенты будут отключаться изящно большую часть времени, но это не может быть гарантировано. В настоящее время кажется, что единственным вариантом является опрос клиента и ожидание CommunicationTimeout, что вряд ли идеально.

Любые предложения с благодарностью.

Ответы [ 5 ]

2 голосов
/ 08 июня 2011

Теоретически, сервис не должен знать о состоянии клиента.Но он может настаивать на том, кого обслуживать, диктуя требования аутентификации, ограничения параллелизма и т. Д.

Если вы хотите, чтобы одновременно обслуживался только один клиент, вы можете просто выбрать режим единого параллелизма.

Например.

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Single)] 
public class CalculatorService : ICalculatorConcurrency 

Это обеспечит одновременную обработку только одного клиентского запроса.Следующая ссылка также может вам помочь.

http://msdn.microsoft.com/en-us/library/ms731193.aspx

РЕДАКТИРОВАТЬ

Если вы считаете, что действия пользователя по сохранению открытого канала мешаютработа другого пользователя, это может не быть обычным случаем.

Поскольку вызов каждого пользователя рассматривается как отдельный сеанс.По умолчанию вызовы WCF считаются созданными для каждого вызова.

Если вы хотите сохранить данные между вызовами пользователя, вы можете выбрать режим экземпляра perSession.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] 
public class CalculatorService : ICalculatorInstance 

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

Вы можете установить режим параллелизма соответственно, то есть Multiple или Reentrant, если хотите.Даже если режим параллелизма является единичным, когда ответ отправляется обратно пользователю, служба будет готова обслужить следующего пользователя.Клиент не будет ждать, чтобы закрыть соединение.Подключение пользователя было бы полезно только для поддержания сеанса в рабочем состоянии.

1 голос
/ 27 июля 2013

Вы можете использовать IChannelInitializer и подключить события сбоя канала и сбоя канала, чтобы обнаружить постепенное или внезапное закрытие клиента.Обратитесь к очень хорошему сообщению об этом Карлоса - http://blogs.msdn.com/b/carlosfigueira/archive/2012/02/14/wcf-extensibility-initializers-instance-context-channel-call-context.aspx

0 голосов
/ 17 июня 2019

Я успешно использовал «детектор отключения», например:

// Code based on https://blogs.msdn.microsoft.com/carlosfigueira/2012/02/13/wcf-extensibility-initializers-instance-context-channel-call-context/
public class WcfDisconnectionDetector : IEndpointBehavior, IChannelInitializer
{
    public event Action Disconnected;
    public int ConnectionCount { get; set; } = 0;

    public WcfDisconnectionDetector() { }
    public WcfDisconnectionDetector(Action onDisconnected) => Disconnected += onDisconnected;

    void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime cr)
        => cr.ChannelInitializers.Add(this);
    void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher ed)
        => ed.ChannelDispatcher.ChannelInitializers.Add(this);
    void IEndpointBehavior.Validate(ServiceEndpoint endpoint) { }
    void IEndpointBehavior.AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }

    void IChannelInitializer.Initialize(IClientChannel channel)
    {
        ConnectionCount++;
        Trace.WriteLine($"Client {channel.SessionId} initialized");
        channel.Closed += OnDisconnect;
        channel.Faulted += OnDisconnect;
    }

    void OnDisconnect(object sender, EventArgs e)
    {
        ConnectionCount--;
        Disconnected?.Invoke();
    }
}

Установите его перед вызовом ServiceHost.Open:

    var detector = new WcfDisconnectionDetector();
    serviceHost.Description.Endpoints.Single().EndpointBehaviors.Add(
      new WcfDisconnectionDetector(() => {/*disconnected*/}));
0 голосов
/ 26 мая 2016
    if (HttpContext.Current.Response.IsClientConnected == false
{
...
}

это может помочь вам

0 голосов
/ 08 июня 2011

Вы можете использовать Операции обратного вызова, чтобы позвонить клиенту, чтобы узнать, подключен ли он.

Взгляните на эту статью в MSDN magazine

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