如何检测断开连接的双工轮询客户端

时间:2010-11-10 19:44:18

标签: silverlight wcf pollingduplexhttpbinding

我已经关注了Tomek Janczuk的Pub/sub sample using HTTP polling duplex WCF channel但是我注意到当客户端通过关闭浏览器而断开连接时,服务在下一次回调时没有注意到。我本来应该有一个例外,或者说某个端点不再存在。

如何知道客户何时离开,以便停止向该客户发布?

4 个答案:

答案 0 :(得分:5)

要确定:不可能

当TCP连接关闭(基于HTTP调用)时,会向服务器发送特殊的TCP消息 - FIN数据包。虽然HTTP是无状态的,但底层TCP连接是有状态的并且保持活动状态,底层TCP连接通常保持打开状态。如果处置客户端,则TCP连接将关闭,并且通常会将消息发送到服务器。但如果它崩溃或其网络断开连接,它将没有时间这样做。总而言之,你永远无法确定。

Here了解更多信息。

答案 1 :(得分:3)

很难,几乎不可能(导致SL双工能力有限)。我们在服务中实现了一个用户列表,我们添加了一个属性“IsDisconnected”和LastCommunicationTime,一旦WCF服务在尝试在用户的Outgoing-Message-Queue中添加消息时获得超时,并且失败,并抛出异常超时我们标记“IsDisconnecte = true”,下次不要尝试将消息发送给该用户。

另一个线程一直在关注它,如果它注意到LastCommunicationTime已超过time值且IsDisconnected = true,则会从列表中删除用户,除非同一用户在此时间段内尝试再次连接(我们通过UserId识别)。

我们手动处理这个问题有很多事情,因为它使WCF服务非常繁忙。

答案 2 :(得分:3)

似乎有一个令人不满意的,虽然简单的解决方案:如果客户端回调超时,请不要再次调用它。

在我的系统中,我还实现了一个手动“检查”调用 - 每隔 n 秒,服务器通过回调通道为每个注册客户端调用无参数方法,只是为了查看客户端是否是还在那儿。我开始怀疑这是不是一个好主意 - 我有一个新问题,其中回调超时一直发生,因为我已经在调试器中暂停了客户端。

答案 3 :(得分:1)

我遇到了这个问题,并使用以下代码创建了一个删除断开连接的客户端的线程。它工作正常,但在10-15分钟后将断开连接的客户端从客户端列表中删除(这对我来说没问题)。

    new Thread(new ThreadStart(() =>
    {
        while (SilverlightClients != null)
        {
                lock (SilverlightClients)
                {
                    SilverlightClients = SilverlightClients.Where(d => (d.Callback as IContextChannel).State != CommunicationState.Opened).ToList();
                }

            Thread.Sleep(1000);
        }
    })) { Name = "Thread Remove Disconnected Clients" }.Start();