All,
I am using SignalR (.net 6) and have couple of questions about SignalR Connections (specifically SignalR connections that use web sockets):
Q #1)
If the SignalR client crashes, will SignalR server dispose the underlying connection automatically for me (and the OnDisconnectedAsync() event will be fired)?
The idea is to dispose client resources (on the server, resource ex: NHibernate session) that are tied to each connection.
My Tests Indicate (on local machine, both server and client):
I tried to simulate this scenario where I had a running client which then I shut down with Task manager and the minute Windows released resources for the process, the SignalR server somehow detected that connection was lost and released the connection and OnDisconnectedAsync() was called. I am not sure if my test was sufficient for this use case (client crash). I am curious of how did the server know, was it the fact the maybe the finalizer for client connection ran?
Q #2) If the current connection between client and server is broken or interrupted and SignalR needs to reconnect, and it successfully reconnects, does it use the same connection (with the same connection ID/same web socket) or does it attempt create new connection (tied to a new web socket)?
https://learn.microsoft.com/en-us/aspnet/core/signalr/configuration?view=aspnetcore-6.0&tabs=dotnet
The server considers the client disconnected if it hasn't received a message (including keep-alive) in this interval. It could take longer than this timeout interval for the client to be marked disconnected due to how this is implemented. The recommended value is double the KeepAliveInterval value.
It assigns a new connection id. Consider using other data to track which user is it, eg. Checking in the on connect and on disconnect methods.
https://learn.microsoft.com/en-us/aspnet/core/signalr/groups?view=aspnetcore-6.0
Related
The System.Net.TcpClient object can only connect to an endpoint once. If the client forces the disconnect, then it is clear that the client needs to be replaced. If the server cancels the connection, then it is possible to test the connection and know when it is no longer connected. However once it has been disconnected, I cannot see any property or method that differentiated the disconnected and used client from a disconnected and fresh client.
What is the correct way to test for a disconnected and used client?
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.
I have a Windows Service running on a client machine which communicates to our server using WCF. The basic process is this:
Every 3 minutes, the client makes a connection to the server using a DuplexChannelFactory (CreateChannel).
While this connection is open, the server sends messages to the client.
The connection must remain open constantly because the server may need to communicate with the client at any time. This is why we are refreshing the connection every few minutes.
For the most part this system works fine. However if the client has a spotty Internet connection, the channel becomes aborted. Here's what happens in this case:
The client opens a connection. This connection stays open for 3 minutes until it is closed and re-opened.
During the first connection, the computer loses Internet connection for a few seconds.
The Windows Service running on the client throws a System.Net.Sockets.SocketException and System.ServiceModel.CommunicationException. The code currently does not catch these exceptions.
The computer regains Internet connection.
The server tries to communicate with the client (still during the first 3 minutes).
Since the first connection is still open, the server cannot communicate and gets the following error: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it has been Aborted.
I'm trying to figure out how I can catch the errors that happen in step 3 so that I can close the current connection and re-open it. I currently have a function to handle the Faulted event, but this event is not hit when the connection is lost. I've tried looking into global error handling but it seems like most of the tutorials are for the server side, not client. Also, since the connection is just staying open indefinitely, there is nowhere I can put a try/catch block since there is no code that is actually running at the time it happens.
I was able to accomplish catching these exceptions by using the FirstChanceException event handler. I had to use this event because the exceptions were being handled automatically deeper down so I couldn't catch them.
In the Windows Service's OnStart function:
Dim currentDomain As AppDomain = AppDomain.CurrentDomain
AddHandler currentDomain.FirstChanceException, AddressOf HandleException
And the function I wrote checks if the exception is of a certain type I know the connection has failed and I create a new connection.
I've started working on a client-server distributed application using WCF. The clients should also send requests to the server, therefore I chose to implement duplex operations using the NetTcpBinding since all the clients will b on the same intranet.
On the server side, for the service class that implements the server contract I use these settings
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single, UseSynchronizationContext = false)]
Every time a client is initialized, I'm creating an instance of the proxy class generated by adding the service using 'Add service reference' option in Visual Studio. After the proxy is initialized, I send a Connect message to the server:
_proxy.InnerChannel.Faulted += new EventHandler(InnerChannel_Faulted);
_proxy.InnerChannel.Closing += new EventHandler(InnerChannel_Closing);
//send a connect message to the server
_proxy.ClientConnected(ClientHostName, Version, ClientID, ClientIP);
Now the server has a reference to the connected client, by using
OperationContext.Current.GetCallbackChannel<IClientEvents>()
This is pretty straight forward, nothing fancy. However, I'm having a bit of trouble with making the client reconnecting to the server after the server went online. In my scenario, I will have up to 50-100 clients connected to the server and they will rarely communicate with the server, let's say in average, 1 request per hour.
What I want to achieve is to have the client "hanging" while the is offline, for this I try to reinitialize the communication channel on the client side every time the channel ends up in Faulted state, which works ok. But when I try to close the server, I get the following message
This could be because a client failed to close a sessionful channel within the required time.
I'm now struggling to find the most appropriate implementation for my scenario:
Not closing the channel after the service call. This way the client will always try to recreate the channel once the connection with the server is down (e.g. interval of 1 min). Doesn't make much sense to keep the channel opened all this time though, so I'm not that sure about this approach.
Closing the channel after each call and recreate when making a new call to the server. This works fine when making service calls, but what happens if the server wants to send a notification the client? The callback reference on the server side will not be valid anymore, I'd have to wait for the client to send a new connect message to get the new callback reference, right? In this case, should I regularly have a different call similar to a Ping() to the server in order to ensure that the server can always contact the client?
I'm still reading materials on WCF duplex operations, just can't decide which approach is better so that I don't run into problems later on.
Thanks for your advice!
I have a simple client server apps that uses WCF (netTcpBinding) when i'm launching the server and sending messages through the client everythings works fine , but when i'm closing the server manually and open it again (without closing the client app at all) the next time the client tries to send a message to the server i get this exception (on the client side):
The socket connection was aborted. This could be caused by an error processing y
our message or a receive timeout being exceeded by the remote host, or an underl
ying network resource issue. Local socket timeout was '00:00:59.9843903'.
if i use basicHttpBinding the problem doesn't occur.
is any one knows why this problem occurs ???
Thanks,
Liran
This is expected behavior. When you close the server, TCP connection on the server is closed and you can't call it from the client anymore. Starting the server again will not help. You have to catch the exception on the client, Abort current proxy and create and open new one.
With BasicHttpBinding it works because NetTcpBinding uses single channel for whole life of the proxy (the cannel is bound to TCP connection) whereas BasicHttpBinding creates new one for each call (it reuses existing HTTP connection or create new one if connection doesn't exist).