A WCF service is based on NetTcpBinding. It may happen that a client silently vanishes, leaving the server without knowledge that it is not connected anymore.
I'm currently using a thread that pings all connected client to see if they are still alive, and removes disconnected clients.
Is a ping thread the correct way to solve the issue, or is there a better, possibly event-based way?
Do I have to surround every code that communicates with the client by try/catch and remove it from the list of connected clients additionally?
I believe I found the answer myself.
There is an event OperationContext.Current.Channel.Closing that is fired on faulted as well as closed connections.
Related
On this previous question: Tell when wcf client lost connection One of the commenters states:
Your service should not care whether a network cable was disconnected.
One feature of TCP is that unless someone is actively sending data, it
can tolerate momentary interruptions in network connectivity.
This is even more true in WCF, where there are layers of extra
framework to help protect you against network unreliability.
I'm having an issue where this is not working correctly. I have WCF client that makes a connection to the server using a DuplexChannelFactory. The connection stays open for 3 minutes. I disconnect the client from the internet and reconnect. The client regains internet connection, however any calls made from the server to that client fail. Once the client reconnects it begins working again.
When I pull the plug on the internet, the client throws several exceptions but the channel is still listed as being in an open state. Once the connection is regained and I made a request from the server to the client, I get errors such as: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it has been Aborted.
Obviously if the request comes in when the client is offline it won't work, but I'm trying to get it so this channel will recover once the internet comes back without having to set up a new connection.
Should this be working as-is, based on the comment I listed above? Or is there something I need to change to make that actually work?
The issue here is that the channel you're trying to use is in a faulted state, and cannot be used any longer (as the error message indicates).
Your client needs to trap (catch) that exception, and then abort the current channel and create a new one. WCF will not do that for you automatically, you have to code for it yourself.
You could also check the CommunicationState of the channel to see if it is faulted, and recover that way.
A final option would be to use the OnFaulted event handler, and when the channel is faulted, abort the channel and create a new one.
Imagine situation (this is real situation):
There is a WCF client application on laptop.
Laptop is connected by WiFi to internet.
User is doing some stuff (request reply operations) on his laptop at work connected to WCF service.
Then user's laptop is sleep-down and user go home. At home user wake-up his laptop, connect HSPDA/3G modem (different interface & ip) and want to continue on work in client appliaction. Note that application hasn't been closed.
User (client application) should be authenticated and if it is possible, communication should be encrypted.
What are the best practices?
Create new proxy for each operation? This should be very slow when initializing net.tcp connection with authentication.
Is solution basicHttp connection (+HTTPS) with InstanceContextMode.PerCall? Note that speed and higher payload is problem.
Or the best solution is something like "wrapper(Func<>)", which contains while loop until operation is successfully finished (on fail, new connection is created and function is called again).
Thanks you for suggestions
I've always kept the connection open for as long as the unit of work is necessary. Basically, the connection is only open and available while the application is performing some processing (and those processes require a WCF connection). It may be more overhead to keep reconnecting (and depending on connection speed it may add latency) but it's also more secure when it comes to having a connection to work with (least probability of failure) and I'm generally saving those resources for other purposes.
However, this all depends on what the application does; If the client is dumb and the service is doing all the work it may make sense to keep the connection as every function executes a method on the service. Though with that comes some failure checking and re-establishing should the connection be unexpectedly severed.
Also, netTcp is going to be a lot faster than wsHttp. And I personally haven't see a lot of latency on establishing a netTcp connection (though I don't know what kind of authentication you're doing [mine has generally implemented windows authentication])
I have always followed the guidance of try/Close/catch/Abort when it comes to a WCF proxy. I am facing a code base now that creates proxies in MVC controllers and just lets them go out of scope. I'm arguing the case that we need to edit the code base to use try/Close/catch/Abort but there is resistance.
Does anyone know a metric (e.g. perfmon) I can capture to illustrate the problem/benefit. Or a definitive reference that spells out the problem/benefit no one can dispute?
You can create a sample application to mimic the problem. Though I haven't tried you can try this,
Create a simple service and limit the maxConcurrentCalls and maxConcurrentSessions to 5.
Create a client application and in that, call the service method without closing the connection.
Fire up 6 or more clients
See what happens when you open a new connection from a client. Probably the client will wait for certain time and you get some exception.
If the client don't close the connection properly, the connection will still remain open in the service so what happens if 1000s of client connected to the service at a time and leave their connections open? The service has a limitation that it could server 'n' connections at a time and because of that the service can't handle any new requests from clients and that's why closing connections are very important.
I think you are aware about the using problem in WCF service. In my applications I close the WCF connections using an extension method as said in this thread.
Have you tried a simple 'netstat -N' from the command prompt both on server and client? Yoy are likely to see a lot of waiting/pending connections which might exhaust your server resources for no reason.
This may be a shot in the dark (I don't know much about the internals of WCF), but here goes...
I'm currently working with a legacy application at a client site and we're experiencing a persistent issue with a WCF service. The application is using the Microsoft Sync Framework 2.0 and syncing through the aforementioned service. The server-side implementation of the service has a lot of custom code in various states of "a mess."
Anyway, we're seeing an error on the client application most of the time and the pattern we're narrowing down centers around different users using the application on the same machine hitting the same service. It seems that the service and the client are getting out of sync in some way on an authentication level.
The error is discussed in an article here, and we're currently investigating the approach of switching from message layer security to transport layer security, which will hopefully solve the problem. However, we may be able to solve it in a less invasive manner if this question makes sense.
In the linked article, one of the suggestions was to forcibly terminate the connection if the specific exception is caught, try again, and if it fails again it wasn't because of this particular theory. Sounds good, and easy to implement. However, I find myself unable to say with confidence if the connection is being properly terminated.
The service operates through a custom interface, which is implemented on the server-side. The only thing that interface can do to end the connection is call EndSession() on the proxy itself, which calls EndSession() on the server which is a custom method.
So...
From a WCF service method, is there a way to properly and gracefully terminate the connection with the client in a way the client will like?
That is, in this custom EndSession() is there some last step I can take to cause the server to completely forget that this connection was open? Because it seems like when another user on the same machine tries to hit the service within the application, that's when it fails with the error in the linked article.
The idea is that, at the client side of things, code which calls EndSession() is followed by nulling out the proxy object, then a factory method is called to supply another one the next time it's needed. So I wonder if something additional needs to happen on the server side (and does by default in WCF were it not for all this custom implementation code) to terminate the connection on that end?
Like I said, a shot in the dark. But maybe in answers/discussions here I can at least further diagnose the problem, so any help is much appreciated. Thanks.
Unfortunately there are only really three ways in which a session can terminated
The client closes the proxy
The service's receiveTimeout is exceeded
before the client sends another
request
the service throws a
non-fault exception which will fault
the channel and so terminate the
session
if you don't want the client involved then you only have 2 and 3 neither of which end well for the client - they will get an exception in both situation on the next attempt to talk to the service.
You could use Duplex messaging and get the service to notify the client that its requires session termination - the client then gets an opportunity to close down the proxy gracefully but this is a cooperative strategy
I'm stuck with a bit of an annoying problem right now.
I've got a Silverlight 4 application (which runs OOB by default). It uses WCF with net.tcp as means of communicating with the server.
The client uses a central instance of the wcf client proxy. As long as everything keeps running on the server side, everything's fine.
If i kill the server in the middle of everything, i drown in an avalanche of exceptions on the client side (connection lost, channel faulted etc etc).
Now i'm looking for a way to handle this in a clean and centralized way (if centralized is possible).
The SL app has one central client object sitting in App.cs (public static MyClient Client { get;set;}), which gets initialized on application start.
Any idea how to properly handle any connectivity problems on the client object?
You mention that you're using a central instance of the WCF client proxy.
If this is the case, then when a server error occurs, the proxy will go into the Faulted state. To keep things centralized, you could cast the client proxy to an ICommuicationObject and attach an event handler to the Faulted event which replaces the faulted proxy, with a new proxy when the event fires.
The usual warnings about thread-safety for centralized access to resources apply!
I think i found a workable - though not centralized - solution. Instead of cluttering the code with try/catch blocks, all it seems to need is a null-check for the event.Error property. If something happened to the connection, this property is always not null. The exceptions only get raised if you try to access event.Result.
It may not be the most beautiful solution, but it appears to work so far.
Perhaps there is a more elegant way though...