Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 787
Joshua Evensen Avatar asked Mar 23 '11 13:03

Joshua Evensen


1 Answers

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!

like image 186
PaulF Avatar answered Sep 18 '22 12:09

PaulF