我使用 HTTP 轮询双工 WCF 通道跟踪了 Tomek Janczuk 的 Pub/sub 示例,但我注意到当客户端通过关闭浏览器断开连接时,服务不会注意到下一次回调。我本来预计会出现异常或其他说明端点不再存在的东西。
您如何知道客户何时离开,从而停止向该客户发布?
我使用 HTTP 轮询双工 WCF 通道跟踪了 Tomek Janczuk 的 Pub/sub 示例,但我注意到当客户端通过关闭浏览器断开连接时,服务不会注意到下一次回调。我本来预计会出现异常或其他说明端点不再存在的东西。
您如何知道客户何时离开,从而停止向该客户发布?
要确定:不可能。
当 TCP 连接关闭时(作为 HTTP 调用的基础),会向服务器发送一个特殊的 TCP 消息 - FIN 数据包。尽管 HTTP 是无状态的,但底层 TCP 连接是有状态的并且通过保持活动状态,底层 TCP 连接通常保持打开状态。如果客户端被释放,则 TCP 连接将关闭,并且通常会向服务器发送一条消息。但是,如果它崩溃或它的网络断开连接,它就没有时间这样做了。所以一言以蔽之,你永远无法确定。
在这里了解更多信息。
它很难,几乎是不可能的(由于 SL 双工功能有限)。我们已经在我们的服务中实现了一个用户列表,并且我们添加了一个属性“IsDisconnected”和 LastCommunicationTime,一旦 WCF 服务在尝试在用户的 Outgoing-Message-Queue 中添加消息时超时,并且失败并引发异常超时。我们标记“IsDisconnecte=true”,下次不要尝试将消息发送给该用户。
另一个线程一直在查看,如果它注意到 LastCommunicationTime 已超过时间值且 IsDisconnected=true,它将从列表中删除用户,除非同一用户尝试在此时间段内再次连接(我们通过其 UserId 识别)。
我们手动做了很多事情来处理这个问题,因为它使 WCF 服务变得如此繁忙。
似乎有一个令人不满意但简单的解决方案:如果客户端回调超时,请不要再次调用它。
在我的系统中,我还实现了手动“检查”调用——每隔n秒,服务器通过回调通道为每个注册的客户端调用一个无参数方法,只是为了查看客户端是否仍然存在。我开始怀疑这是否真的是一个好主意——我遇到了一个新问题,即回调超时不断发生,因为我已经在调试器中暂停了客户端。
我遇到了这个问题,并使用以下代码创建了一个删除断开连接的客户端的线程。它工作正常,但在 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();