我们如何检测WCF客户端何时断开连接?

时间:2011-06-08 14:38:45

标签: wcf

有没有办法找出WCF客户端断开连接的时间。目前唯一的方法似乎是等到服务器上客户端的呼叫最终超时。

我已经尝试订阅OperationContext.Current.Channel.Faulted事件,但遗憾的是它从未被调用过;我的理解是,当客户端消失时,应该触发此事件。另一方面,当事件关闭时,优雅地调用OperationContext.Current.Channel.Closed。

在我们的应用程序中,我们一次只支持单个客户端连接,因此当有人关闭并重新启动客户端应用程序时,如果服务器可以知道断开连接,优雅地整理然后接受将会很好另一个联系。

是的,客户端大部分时间会优雅地断开连接,但这不能保证。目前唯一的选择似乎是轮询客户端并等待CommunicationTimeout,这几乎不理想。

任何建议都非常感谢。

5 个答案:

答案 0 :(得分:2)

理论上,服务不需要了解客户的状态。但它可以通过规定身份验证需求,并发限制等来坚持为谁服务。

如果您打算确保一次只提供一个客户端,则可以选择单一并发模式。

例如。

[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 :(得分:0)

您可以使用回拨操作来调用客户端以查看它是否仍然连接。

MSDN magazine

上查看这篇文章

答案 2 :(得分:0)

您可以使用IChannelInitializer并挂断Channel Close和Channel故障事件来检测客户端的正常或突然关闭。请参阅Carlos的一篇非常好的帖子 - http://blogs.msdn.com/b/carlosfigueira/archive/2012/02/14/wcf-extensibility-initializers-instance-context-channel-call-context.aspx

答案 3 :(得分:0)

    if (HttpContext.Current.Response.IsClientConnected == false
{
...
}

它可以帮到你

答案 4 :(得分:0)

我成功使用了这样的“断开检测器”:

// 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*/}));