Any way to tell if a DuplexClientBase is busy? - wcf

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.

Related

ASAP initialization of WCF duplex nettcp channel

In my client/server applications, I want a single duplex WCF channel to be available for communication with its server - sort of a background connection that isn't strictly necessary for the client application to run, but is desirable for reporting status to the server. I have a Ping() call and Echo() callback in the IServerContract and IClientContract respectively.
I implement class ServerProxy : System.ServiceModel.DuplexClientBase<IServerContract> with the pass-thru methods to base.InnerChannel.
If I create var proxy = new ServerProxy(...) in my client, I can just begin calling proxy.Ping() and WCF will automatically open the connection for the first call and perform the operation call immediately after. However, the first call always takes ~10 seconds because of channel initialization and authentication. (I'm using windows authentication, Message-based security, EncryptAndSign.) Subsequent calls are quicker.
I believe this 10 seconds is unavoidable, but there is usually time prior to the first call by the client to the server during which this initialization could happen. So rather than wait for the auto-open feature of DuplexClientBase, I open the channel early with a call to proxy.InnerDuplexChannel.Open(). (proxy.Open() throws an exception and this indirection seems to avoid it.)
Unfortunately, authenticating the client-to-server channel does not also authenticate the server-to-client callback channel. Instead, the first call by the server to the client ALSO requires ~10 seconds. Since I'm using netTcp binding I'm surprised by this, but I'll assume it is to be expected for now.
How can I open the callback channel preemptively as well?
I could require the client to call some Login() method instead, but I don't believe that WCF should strictly require an operation before user-code can be aware of a connected client!
Hint(?): I imagine that this code would have to go in a place in the WCF pipeline/lifecycle where the server has the opportunity to perform custom actions upon a client-connected event (and BEFORE any operation message is transmitted). This integration point has so far eluded me.

Check availability of WCF Callback Service

I have a service that uses callback operations to call back its client. Is there a away to notify the client when Service goes down? An exception is raised when client goes down during callback, but with service goes down the subscription is lost but client is not notified.
Does WCF support some heartbeat operation to check the state of the service?
Thanks
No, there's no such thing as a "check if this service call will succeed" method.
You need to call the service and be prepared to handle any exceptions that occur during the service call.
There's really no reliable or useful way to check for service availability. All that a heartbeat could check for is that you can call your service method right now - but a fraction of a second later, that connection might be gone (cable has been unplugged or severed, server has crashed - the possibilities of things going wrong are endless......), too. It cannot check if all the necessary background services and databases etc. are available.
So in reality, such a heartbeat check is quite pointless. Just call the service, hope for the best, and be prepared for the worst! Wrap your service calls in good exception handling, and get on with it.

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

WCF Server Push connectivity test. Ping()?

Using techniques as hinted at in:
http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.callbackcontract.aspx
I am implementing a ServerPush setup for my API to get realtime notifications from a server of events (no polling). Basically, the Server has a RegisterMe() and UnregisterMe() method and the client has a callback method called Announcement(string message) that, through the CallbackContract mechanisms in WCF, the server can call. This seems to work well.
Unfortunately, in this setup, if the Server were to crash or is otherwise unavailable, the Client won't know since it is only listening for messages. Silence on the line could mean no Announcements or it could mean that the server is not available.
Since my goal is to reduce polling rather than immediacy, I don't mind adding a void Ping() method on the Server alongside RegisterMe() and UnregisterMe() that merely exists to test connectivity of to the server. Periodically testing this method would, I believe, ensure that we're still connected (and also that no Announcements have been dropped by the transport, since this is TCP)
But is the Ping() method necessary or is this connectivity test otherwise available as part of WCF by default - like serverProxy.IsStillConnected() or something. As I understand it, the channel's State would only return Faulted or Closed AFTER a failed Ping(), but not instead of it.
2) From a broader perspective, is this callback approach solid? This is not for http or ajax - the number of connected clients will be few (tens of clients, max). Are there serious problems with this approach? As this seems to be a mild risk, how can I limit a slow/malicious client from blocking the server by not processing it's callback queue fast enough? Is there a kind of timeout specific to the callback that I can set without affecting other operations?
Your approach sounds reasonable, here are some links that may or may not help (they are not quite exactly related):
Detecting Client Death in WCF Duplex Contracts
http://tomasz.janczuk.org/2009/08/performance-of-http-polling-duplex.html
Having some health check built into your application protocol makes sense.
If you are worried about malicious clients, then add authorization.
The second link I shared above has a sample pub/sub server, you might be able to use this code. A couple things to watch out for -- consider pushing notifications via async calls or on a separate thread. And set the sendTimeout on the tcp binding.
HTH
I wrote a WCF application and encountered a similar problem. My server checked clients had not 'plug pulled' by periodically sending a ping to them. The actual send method (it was asynchronous being a server) had a timeout of 30 seconds. The client simply checked it received the data every 30 seconds, while the server would catch an exception if the timeout was reached.
Authorisation was required to connect to the server (by using the built-in feature of WCF that force the connecting person to call a particular method first) so from a malicious client perspective you could easily add code to check and ban their account if they do something suspicious, while disconnecting users who do not authenticate.
As the server I wrote was asynchronous, there wasn't any way to really block it. I guess that addresses your last point, as the asynchronous send method fires off the ping (and any other sending of data) and returns immediately. In the SendEnd method it would catch the timeout exception (sometimes multiple for the client) and disconnect them, without any blocking or freezing of the server.
Hope that helps.
You could use a publisher / subscriber service similar to the one suggested by Juval:
http://msdn.microsoft.com/en-us/magazine/cc163537.aspx
This would allow you to persist the subscribers if losing the server is a typical scenario. The publish method in this example also calls each subscribers on a separate thread, so a few dead subscribers will not block others...

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