有没有办法找出WCF客户端断开连接的时间。目前唯一的方法似乎是等到服务器上客户端的呼叫最终超时。
我已经尝试订阅OperationContext.Current.Channel.Faulted事件,但遗憾的是它从未被调用过;我的理解是,当客户端消失时,应该触发此事件。另一方面,当事件关闭时,优雅地调用OperationContext.Current.Channel.Closed。
在我们的应用程序中,我们一次只支持单个客户端连接,因此当有人关闭并重新启动客户端应用程序时,如果服务器可以知道断开连接,优雅地整理然后接受将会很好另一个联系。
是的,客户端大部分时间会优雅地断开连接,但这不能保证。目前唯一的选择似乎是轮询客户端并等待CommunicationTimeout,这几乎不理想。
任何建议都非常感谢。
答案 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)
您可以使用回拨操作来调用客户端以查看它是否仍然连接。
上查看这篇文章答案 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*/}));