I am trying to set Disconnect Timeout to higher value from the default 30s.
All examples on web are more JS oriented.
var hubConnection = new HubConnection("http://localhost:8087");
var testHubProxy = hubConnection.CreateHubProxy("TestHub");
Error: System.TimeoutException: Couldn't reconnect within the configured timeout of 00:00:30, disconnecting.
This did not work:
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(35);
Update:
It looks like DisconnectTimeout needs to be set on the server side!?
What is the reason for disallowing different clients to have different Disconnect Timeout?
Disconnect Timeout is configured on server-side. The main reasons could be as follows:
We know the server may take some N-time units to respond so that the all clients may be well aware.
The server should be pinging the clients for connection at regular times. So the server is aware of clients connection and can manage other hubs and eradicate the expired connections from its connection pool.
The client is not supposed to set disconnect timeout because it does not know when could it shutdown e.g. the internet switched off accidentally on client side than the client is not able to tell server that I am not going to connect to you again. Yes but we have some events at client-side which tells it that it is not connected to the signalr hub anymore. Please see the reconnecting and disconnected events.
Summary:
Disconnect timeout is to inform the server that its client is not connected anymore even if it disconnects disgracefully .
Related
In our setup we have a WCF client in a windows service that needs to request configuration from a central server hosting a WCF endpoint. Client/Server communication works like a charm when the client machine is fully up and running but fails during boot.
below is the Exception throw:
EXCEPTION THROWN: System.TimeoutException: Client is unable to finish
the security negotiation within the configured timeout
(00:00:19.9839990). The current negotiation leg is 1
(00:00:19.8689925).---> System.TimeoutException: The request channel
timed out attempting to send after 00:00:19.8689925. Increase the
timeout value passed to the call to Request or increase the
SendTimeout value on the Binding. The time allotted to this operation
may have been a portion of a longer timeout
The channel connection is secured with var binding = new WSHttpBinding("SecureWsHttpBinding") and Certificates.
I have tried with various increasing OperationTimeout values from 60s to 120s with basically the same result.
At the time when the Exception occur the network card is up and running.
Do anybody know why this is happening under these conditions? Do SecureWsHttpBinding require some windows services to run?
I have a WCF service that creates its own secondary IP (using netsh) upon startup and listens on that IP. Sometimes it just so happens that the when server starts listening clients from the same machine can't connect (client credentials are rejected). From other machines, however, there are no such connection problems.
When starting service on the original IP, connection problems don't seem to occur, but the non-deterministic behavior of the previous scenario prevents me from making any conclusions.
This is what is used for credentials and protection level:
TcpClientCredentialType clientCredentialType = TcpClientCredentialType.Windows;
ProtectionLevel protectionLevel = ProtectionLevel.EncryptAndSign;
I would like to know what is happening here. Any suggestions/insights are welcome.
I'd like to wait for a slow response from a client with TcpClient but get a timeout after about 20s no matter how I configure it. This is my attempt:
using (var client = new TcpClient { ReceiveTimeout = 9999999, SendTimeout = 9999999 })
{
await client.ConnectAsync(ip, port);
using (var stream = client.GetStream())
{
// Some quick read/writes happen here via the stream with stream.Write() and stream.Read(), successfully.
// Now the remote host is calculating something long and will reply if finished. This throws the below exception however instead of waiting for >20s.
var bytesRead = await stream.ReadAsync(new byte[8], 0, 8);
}
}
The exception is an IOException:
Unable to read data from the transport connection: A connection
attempt failed because the connected party did not properly respond
after a period of time, or established connection failed because
connected host has failed to respond.
...which contains a SocketException inside:
A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection
failed because connected host has failed to respond
SocketErrorCode is TimedOut.
The 20s seems to be an OS default on Windows but isn't it possible to override it from managed code by interacting with TcpClient? Or how can I wait for the response otherwise?
I've also tried the old-style BeginRead-EndRead way and the same happens on EndRead. The problem is also not caused by Windows Firewall or Defender.
I'd like to wait for a slow response from a client
It's important to note that it's the connection that is failing. The connection timeout is only for establishing a connection, which should always be very fast. In fact, the OS will accept connections on behalf of an application, so you're literally just talking about a packet round-trip. 21 seconds should be plenty.
Once the connection is established, then you can just remove the ReceiveTimeout/SendTimeout and use asynchronous reads to wait forever.
It turns out that the remote host wasn't responding in a timely manner, hence the problem. Let me elaborate, and though this will be a solution very specific to my case maybe it will be useful for others too.
The real issue wasn't a timeout per se, as the exception indicated, but rather what exceptions thrown on subsequent Read() calls have shown: "An existing connection was forcibly closed by the remote host"
The remote host wasn't purposely closing the connection. Rather what happened is that when it was slow to respond it was actually so busy that it wasn't processing any TCP traffic either. While the local host wasn't explicitly sending anything while waiting for a response this still was an issue: the local host tried to send ACKs for previous transmissions of the remote host. Since these couldn't be delivered the local host determined that the remote host "forcibly closed" the connection.
I got the clue from looking at the traffic with Wireshark (always good to try to look at what's beneath the surface instead of guessing around): it was apparent that while the remote host was busy it showed complete radio silence. At the same time Wireshark showed retransmission attempts carried out by the local host, indicating that this is behind the issue.
Thus the solution couldn't be implemented on the local host either, the behavior of the remote host needed to be changed.
The problem
I have a .NET Client application that makes use of HubConnectionManager to retry connecting to the server if my app changes to the Closed state.
It seems to work great in the following instances:
For short disconnects (e.g. restarting the SignalR server) it immediately reconnects and picks up where it left off.
For longer disconnects (if the server is down for more than 30 seconds), it will go from connected->reconnecting->disconnected and then connect again just fine.
HOWEVER, in case (2), while the client has successfully reconnected, none of the events that the client previously subscribed to come through anymore. So, in effect, the client is connected but effectively dead.
What I've Tried
So reconnecting works in all cases, but if I reconnect after a disconnect I lose my subscriptions.
Therefore, I initially tried to capture the StateChanged event and, upon changing from Connecting to Connected, re-subscribe to the server's broadcasts (e.g. _hubProxy.On<MachineStatusDto>(UPDATE_MACHINE_STATUS, BroadcastMachineStatus);). However, this doesn't appear to work and I am concerned that, if I am not careful, I could create memory leaks just like subscribing using += multiple times.
Not sure where to go from here...
Misc. Details
The client is WPF (.NET 4 compatible)
The server is a Windows Service self-hosting SignalR (skys-the-limit .NET 4.5.2)
Client and Server are in the same building, infinite retry on connections is A-OK.
This is for an internal LoB app, so broad use across the internet and such isn't a requirement
After further investigation, and running my own Client/Server on HubConnectionManager, I realized that I am actually reconnecting and receiving subscriptions afterwards.
The caveat with my LoB application is that my subscriptions are based on a Group membership. According to MSDN:
"When reconnecting after a temporary disruption, the user
automatically re-joins the previously-assigned groups. Automatically
rejoining a group only applies when reconnecting, not when
establishing a new connection."
Therefore, I was reconnecting successfully and would have received any global messages sent by the server. However, I have to re-add my clients to their respective Group when re-establishing a connection after a DisconnectTimeout.
Here's the code I use:
//Somewhere when initializing the connection
_hubConnectionManager.StateChanged += OnHubConnectionManagerOnStateChanged;
//Handler for state change
private void OnHubConnectionManagerOnStateChanged(StateChange st)
{
//When disconnected, set state variable
if (st.NewState == ConnectionState.Disconnected)
{
_wasDisconnected = true;
}
//If disconnected and we re-create connection successfully, re-subscribe to updates.
if (_wasDisconnected && st.OldState == ConnectionState.Connecting && st.NewState == ConnectionState.Connected)
{
SubscribeToMachine(MachineStatusDetails.MachineId);
}
Messenger.Default.Send<ConnectionState>(st.NewState, UIMessageToken.ConnectionState);
}
Error:
Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall
Situation
There is a TCP Server
My web application connects to this TCP Server
Using the below code:
TcpClientInfo = new TcpClient();
_result = TcpClientInfo.BeginConnect(<serverAddress>,<portNumber>, null, null);
bool success = _result.AsyncWaitHandle.WaitOne(20000, true);
if (!success)
{
TcpClientInfo.Close();
throw new Exception("Connection Timeout: Failed to establish connection.");
}
NetworkStreamInfo = TcpClientInfo.GetStream();
NetworkStreamInfo.ReadTimeout = 20000;
2 Users use the same application from two different location to access information from this server at the SAME TIME
Server takes around 2sec to reply
Both Connect
But One of the user gets above error
"Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall"
when trying to read data from stream
How can I resolve this issue?
Use a better way of connecting to the server
Can't because it's a server issue
if a server issue, how should the server handle request to avoid this problem
This looks Windows-specific to me, which isn't my strong point, but...
You don't show us the server code, only the client code. I can only assume, then, that your server code accepts a socket connection, does its magic, sends something back, and closes the client connection. If this is your case, then that's the problem.
The accept() call is a blocking one that waits for the next client connection attempt and binds to it. There may be a queue of connection attempts created and administered by the OS, but it can still only accept one connection at a time.
If you want to be able to handle multiple simultaneous requests, you have to change your server to call accept(), and when a new connection comes in, launch a worker thread/process to handle the request and go back to the top of the loop where the accept() is. So the main loop hands off the actual work to another thread/process so it can get back to the business of waiting for the next connection attempt.
Real server applications are more complex than this. They launch a bunch of "worker bee" threads/processes in a pool and reuse them for future requests. Web servers do this, for instance.
If my assumptions about your server code are wrong, please enlighten us as to what it looks like.
Just a thought.
If your server takes 2seconds to response, shouldn't the Timeout values be 2000, instead of 20000 (which is 20 seconds)? First argument for AsyncWaitHandle.WaitOne() is in milliseconds.
If you are waiting 20 seconds, may be your server is disconnecting you for being idle?