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

发布于 2024-10-01 11:15:48 字数 262 浏览 0 评论 0原文

我遵循 Tomek Janczuk 的 使用 HTTP 的 Pub/sub 示例轮询双工 WCF 通道,但我注意到,当客户端通过关闭浏览器断开连接时,服务不会注意到下一个回调。我本以为会出现异常或出现端点不再存在的情况。

如何知道客户端何时消失,从而停止向该客户端发布内容?

I have followed Tomek Janczuk's Pub/sub sample using HTTP polling duplex WCF channel but I've noticed that when a client disconnects by closing the browser the service does not notice on the next callback. I would have expected an exception or something to say that the endpoint was not there any longer.

How can you know when a client is gone, so as to stop publishing to that client?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

栀子花开つ 2024-10-08 11:15:48

要确定的是:不可能

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

此处了解更多信息。

To know for sure: impossible.

When a TCP connection is closed (underlying an HTTP call), a special TCP message is sent to the server - FIN packet. Although HTTP is stateless, underlying TCP connection is stateful and with keep alive, underlying TCP connection usually stays open. If client is disposed, TCP connection is closed and normally a message sent to the server. But if it crashes or its network is disconnected, it would not have the time to do this. So in one word, you can never be sure.

Here for more info.

月下伊人醉 2024-10-08 11:15:48

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

在我的系统中,我还实现了手动“检查”调用 - 每 n 秒,服务器通过回调通道为每个注册的客户端调用一个无参数方法,只是为了查看客户端是否仍然存在。我开始怀疑这是否真的是一个好主意 - 我遇到了一个新问题,因为我已在调试器中挂起客户端,所以回调超时不断发生。

It seems there's one unsatisfactory, albeit simple solution: If the client callback times out, don't call it again.

In my system I've also implemented a manual "check" call - every n seconds the server calls a parameterless method over the callback channel for each registered client, just to see if the client is still there. I'm starting to wonder if that really was a good idea - I've got a new problem where a callback timeout keeps occurring because I've suspended the client in the debugger.

与之呼应 2024-10-08 11:15:48

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

另一个线程继续查看该情况,如果它注意到 LastCommunicationTime 已超过某个时间值且 IsDisconnected=true,则会将该用户从列表中删除,除非同一用户尝试在此时间段内再次连接(我们通过其 UserId 进行识别)。

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

Its hard, almost impossible (cause of limited SL duplex capabilities). we have implemented a list of users in our service, and we have added a property "IsDisconnected" and LastCommunicationTime, once WCF service gets a timeout when tries to add a message in user's Outgoing-Message-Queue, and fails, and throws an exception of timeout. we mark "IsDisconnecte=true" and next time don't try to send the message to that user.

Another thread keeps looking at that and if it notice that the LastCommunicationTime has been exceeded by a value of time and IsDisconnected=true, it removes the user from the list, unless the same user tries to get connected again within this time period (which we identify by its UserId).

There are so many things we did manually to handle this problem as it was making the WCF service so much busy.

︶ ̄淡然 2024-10-08 11:15:48

我遇到了这个问题,并创建了一个线程,使用以下代码删除断开连接的客户端。它工作正常,但在 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();

I faced this problem and created a thread that removes disconnected clients with the following code. It works fine but drops the disconnected client from the client list after 10-15 minutes (which was ok for me).

    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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文