How to detect diconnected Duplex Polling clients
Asked Answered
D

4

6

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?

Digiacomo answered 10/11, 2010 at 19:44 Comment(1)
Are the callback methods "OneWay"? Would setting IsOneWay to false on the OperationContract attribute make server detect timeouts? (Commenting not answering, because I'm not sure)Episternum
E
3

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.

Episternum answered 11/11, 2010 at 4:49 Comment(2)
In my initial testing, the issue is that I don't get the timeout. I'm toying with an approach similar too yours except in reverse. The clients "ping" the server and if the server hasn't heard from them in a set amount of time, they are off the list, which I beleive is similar to the asp.net session management.Digiacomo
@Ralph - I was using netTcpBinding (it was a thick client, not Silverlight). Maybe the PollingDuplexHttp binding just doesn't time-out, in which case the solution you've described would be the only option.Episternum
D
5

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.

Doody answered 10/11, 2010 at 19:53 Comment(1)
In one word, I like this answer. :-)Kimmel
C
3

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.

Cartilaginous answered 10/11, 2010 at 20:27 Comment(3)
I've ended up adopting a very similar pattern.Digiacomo
But remember: This makes another problem, server is too much smart now and always ready to kick out the users :), What about those users which are not gone but are very silent but somehow their "make connection call has been failed" and their client's channel has came under fault, in that case they would have to open the channel once again which gives them a new session-Id, and that channel would be new to server. So upon registration on server once agian, server should delete the old user item from List and add a new one/ Or update it with new one (ClientCallback Channel is very imp in that)Cartilaginous
when Client's channel gets faulted cause of "when make-connection request gets failed". server doesn't know about it instantly. And Client.ChannelFaulted fires on server when serverPooltimeout exceeds. Which is a "Blind Move of WCF service", if you know what i mean. Although i'm not sure about serverPooltimeout in that case 100%, honestly, i found it kind of random time.Cartilaginous
E
3

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.

Episternum answered 11/11, 2010 at 4:49 Comment(2)
In my initial testing, the issue is that I don't get the timeout. I'm toying with an approach similar too yours except in reverse. The clients "ping" the server and if the server hasn't heard from them in a set amount of time, they are off the list, which I beleive is similar to the asp.net session management.Digiacomo
@Ralph - I was using netTcpBinding (it was a thick client, not Silverlight). Maybe the PollingDuplexHttp binding just doesn't time-out, in which case the solution you've described would be the only option.Episternum
P
1

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();
Parsimony answered 12/5, 2011 at 7:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.