Recover Callback channel after CommunicationObjectAbortedException thrown - wcf

We have (Multiple)Clients-(One)Server architecture for poker desktop game. We are using callback Notifications using callback Channels.
But sometimes because of internet connection drops, that particualr client gets disconected from server and that particular's client's WCF channel is also gone to faluted state and his callback Channel which lies in server is also faluted.
Scenario :
That client is playing game, while internet connection drops, that game is stopped, still his game window remains open and when his/her internet connection gets back that client is dropped out from Server, but that player's game window still opens and that player can't do anything as his/her WCF channel is dropped out.
We want to close that particular client's window while he/she is dropped out from server and throwing 'CommunicationObjectAbortedException ' exception.
We can't use previous WCF channel's callback channel as it's in faluted state.
So we have tried to create new callbackChannel in server while dropping using below code :
OperationContext.Current.GetCallbackChannel();
but here Current is showing "NULL" as that player's WCF channel is aborted, so it's throwing an error that "Object reference not set to an instance of object".
So is there any solution to use aborted WCF channel's callback Channel or recover that WCF channel without reinitializing them or to call that client using new channel?

I'd try following:
On server side, when trying to communicate using faulted / aborted chanel - you'll failed.
Catch this failure, and remove its callback from the list (I suppose you manage some callback list).
On client side - when chanel Faulted / ... handled - try to re-open new chanel to server. When this new chenel will be open, on server side place this new callback back to the "valid callbacks" list.

Related

Any way to tell if a DuplexClientBase is busy?

I was looking at Microsoft's duplex WCF sample:
It starts here but the interesting bit is here at the end with the client.
// Wait for callback messages to complete before
// closing.
System.Threading.Thread.Sleep(5000);
// Close the WCF client.
wcfClient.Close();
Console.WriteLine("Done!");
If you take out the Sleep, you will get an exception
The session was closed before message transfer was complete.
So clearly the client knows there's stuff in the air, is there a way to ask it for its current status? There's a state but that just defines whether it's open or closed (i.e. connected not active).
This is not entirely true. Your methods are one-way method calls. So, when you call the service from your client, that call (or set of calls) is completed. In other words, the "message" has been delivered to the service and there is no expectation for a response since it is one-way. It might callback on the callback contract...it might not.
When you setup Duplex channel, you're standing up an endpoint for the service to call back on (client becomes a service essentially). If you close the client, then if/when the service decides to call back, the communication exception will occur. That's just the way this message exchange pattern works.
You really sort of answered your own question. Which is, when you check the status it is either open, closed (or faulted). When you're using a duplex channel, open in this case means there is potentially "activity" on the channel. That's why the sleep is there - to allow the service time to call back. If you look at the SDK sample (http://msdn.microsoft.com/en-us/library/vstudio/ms752216(v=vs.110).aspx), it's basically doing the same thing except it sits there waiting for you to press ENTER before it closes the client application.
So, in a real application (not a console based sample like these are), either keep your client proxy active or change your message exchange pattern to a request/reply pattern.

keeping a wcf callback channel open indefinitely / reconnecting from client if it faults

i'm currently trying to set up something like this:
a server side windows wcf service hangs out and listens via tcp for connections from a client side windows service.
when a connection is received (the client calls the CheckIn method on the service) the service obtains a callback channel via OperationContext.Current.GetCallbackChannel<T>
this channel is stored in a collection along with a unique key (specifically, i store the callback interface, the channel, and the key in a List<ClientConnection> where each of those is a property)
calls should now be able to be passed to that client service based on said unique key
this works at first, but after a while stops -- i'm no longer able to pass calls to the client. i'm assuming it's because the connection has been dropped internally and i'm trying to work with a dead connection.
that in mind, i've got the following questions:
how do i tell wcf i want to keep those tcp connections indefinitely (or for as long as possible)?
how do i check, from the client side, whether or not my connection to the server is still valid so i can drop it and check in with the server again if my connection is fried?
i can think of gimpy solutions, but I'm hoping someone here will tell me the RIGHT way.
When you establish the connection from the client, you should set two timeout values in your tcp binding (the binding that you will pass to ClientBase<> or DuplexClientBase<>):
NetTcpBinding binding = new NetTcpBinding();
binding.ReceiveTimeout = TimeSpan.FromHours(20f);
binding.ReliableSession.InactivityTimeout = TimeSpan.FromHours(20f);
My sample uses 20 hours for timeout, you can use whatever value makes sense for you. Then WCF will attempt to keep your client and server connected for this period of time. The default is relatively brief (perhaps 5 minutes?) and could explain why your connection is dropped.
Whenever there is a communication problem between the client and server (including WCF itself dropping the channel), WCF will raise a Faulted event in the client, which you can handle to do whatever you feel appropriate. In my project, I cast my DuplexClientBase<> derived object to ICommunicationObject to get a hold of the Faulted event and forward it to an event called OnFaulted exposed in my class:
ICommunicationObject communicationObject = this as ICommunicationObject;
communicationObject.Faulted +=
new EventHandler((sender, e) => { OnFaulted(sender, e); });
In the above code snippet, this is an instance of my WCF client type, which in my case is derived from DuplexClientBase<>. What you do in this event is specific to your application. In my case, the application is a non-critical UI, so if there is a WCF fault I simply display a message box to the end-user and shut down the app - it'd be a nice world if it were always this easy!

How to detect client-side if the server disconnects me?

I have a WCF self-hosted service with a net.tcp DuplexChannel. On the server I run the following to disconnect a client:
((ICommunicationObject)client.CallbackChannel).Close();
This works fine but how do I detect on the client that it has been disconnected?
Ive hooked up to Closed and Faulted-events on both the InstanceContext of the callback and the channel to the server:
InstanceContext callback = new InstanceContext(callbackImp);
callback.Closed += new EventHandler(callback_Closed);
and
((ICommunicationObject)Channel).Closed += new EventHandler(Channel_Closed);
But nothing works. I never get notified. The workaround Im using now is to have a method in the callback that triggers a disconnect from the client-side instead. But I rather not do it this way. I especially dont want to let the server wait for a user to disconnect.
EDIT
I just realized that when disconnecting from client-side I run a method in the service-contract which is marked with IsTerminating = true:
[OperationContract(IsTerminating = true)]
void Disconnect();
I figured it would be the same on the callback-contract then? I tried adding the same method to my callback and it did terminate the callback-channel from the server point of view but I still didnt got notified on the client-side...weird
EDIT
I found out some more info about this:
When the server aborts the callback
channel, a fault travels back to the
client, the client faults and we get
the Faulted event on the client.
When the server closes the callback
channel, the session is still open
until the client issues the close.
Once the client closes the channel
you'll see the Closed event.
According to this statement the Close-event is not triggered mearly by closing the callbackchannel from the server, the client has to close it as well. So I could run Close on the client in the terminating Disconnect-method of the callback. Or I could use the Abort-method on the callback server-side and skip using a Disconnect-method on the callback. I dont know which one I preffer honestly. Hmmmm.
EDIT
I went with the Abort-approach. It seemed like the most logical method and it works really well. The client gets notified with the Faulted-event on the callback-instancecontext. Nice.
I went with the Abort-approach. It seemed like the most logical method and it works really well. The client gets notified with the Faulted-event on the callback-instancecontext.
You can simply do a callback just before closing the callback channel telling the client you're closing the channel.
So just before this line of code:
((ICommunicationObject)client.CallbackChannel).Close();

How do I properly handle a faulted WCF connection?

In my client program, there is a WCF connection that is opened at startup and supposedly stays connected til shutdown. However, there is a chance that the server closes due to unforeseeable circumstances (imagine someone pulling the cable).
Since the client uses a lot of contract methods in a lot of places, I don't want to add a try/catch on every method call.
I've got 2 ideas for handling this issue:
Create a method that takes a delegate and executes the delegate inside a try/catch and returns an Exception in case of a known exception, or null else. The caller has to deal with nun-null results.
Listen to the Faulted event of the underlying CommunicationObject. But I don't see how I could handle the event except for displaying some error message and shutting down.
Are there some best practices for faulted WCF connection that exist for app lifetime?
If you do have both ends of the wire under your control - both the server and the client are .NET apps - you could think about this approach instead:
put all your service and data contracts into a shared assembly, that both the server and the client will use
create the ChannelFactory<IYourService> at startup time and cache it; since it needs to have access to the service contract, this only works if you can share the actual service contract between server and client. This operation is the expensive part of building the WCF client
ChannelFactory<IYourService> factory = new ChannelFactory<IYourService>();
create the actual communications channel between client and server each time you make a call, based on the ChannelFactory. This is pretty cheap and doesn't cost much time - and you can totally skip any thoughts about having to detect or deal with faulted channels.....
IYourService client = factory.CreateChannel();
client.CallYourServiceMethod();
Otherwise, what you basically need to do is wrap all service calls into a method, which will first check for a channel's faulted state, and if the client proxy is faulted, aborts the current one and re-creates a new one.
I wrote a blog post on exceptions in WCF that deals with how to handle this: http://jamescbender.com/bendersblog/Default.aspx

How to be notified if WCF Duplex session is prematurely closed

I have a publish/subscribe scenario in WCF using net.tcp and Duplex callbacks. I have a number of clients that subscribe to the service, and this works fine. However, sometimes a client will close without unsubsribing (Client computer goes to sleep, computer crashes, network connection is aborted, etc..), this causes an exception to be thrown when I callback via my callback list.
Now, I can certainly catch the exception and remove the offending callback, but this seems less like an exception scenario to me and further along the lines of "expected behavior".
Is there an event that gets fired on connection close that will notify me so that I can remove the callback from my list? Consider that this is net.tcp and not HTTP, so connection state should be known.
Clearly the framework knows the connection has been closed and disposed because the exception is something along the lines of "attempt to call a disposed object".
EDIT:
I should point out, that this is not a long running transaction. It's a long running connection in a publish/subscribe scenario. Basically, the callback is used to notify transient subscribers of various events as they happen. Each event is isolated and not long running.
It has been a while, this is from memory so I could be wrong, but I think perhaps if you make an IEndpointBehavior that goes an pokes at the DispatchRuntime to add an IInputSessionShutdown, then you can get notified when the session channel ends.
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.dispatchruntime.inputsessionshutdownhandlers.aspx