If no data is received over stream tcpclient close the connection - c#

I would like to know on TcpClient's NetworkStream what exactly happen if timeout occurs.
While debugging the code i found that after request is sent and if no data is received within mention timeout period it throws below exception and unfortunately closes the connection (TcpClient.Connected become false):
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.
It throws the exception is okay, but i would like to know how i can prevent it from closing the connection.
It would be great if someone can provide more insights on this.

Have you checked this one? Reconnect TCPClient after interruption I think if you have a long enough TTL of your TCP Connection, should an exception occurs (I believe you would get thrown a SocketException) you can catch that up and initiate your retry logic. There are several implementations for this and obviously that would depend on the use case but normally there is a number of attempts (configuration value) before "giving up" connecting. That way your manager will retry connecting X number of times and will carry on if there is a successful connection otherwise will propagate up in the chain the exception.

Related

C# TcpClient - What's the best way for a client to determine if remote server has gracefully shutdown connection?

I know there are various suggested ways to achieve this, using Poll/Available/Send, etc., but none of them seem to work for me. I have a connection to a remote server, which the remote server gracefully disconnects after a specific message. I need to ensure I don't disconnect from the remote server myself, and wait for the server to shutdown connection before I can safely reconnect and send other follow-up messages.
I'm using the ReadAsync method on Stream to get responses from that connection, as below:
while (await TcpClientObject.GetStream().ReadAsync(bufferData, 0, bufferData.Length) > 0)
{
//My logic here to handle responses
}
What's the most recommended approach for me to verify that the remote server has gracefully shutdown the connection before attempting a reconnect? Thanks.
If everything goes well ReadAsync will return 0 when the server closes the connection.
An exception is thrown if your side detects an abnormal disconnection, but in the worst case your end still thinks it's connected and ReadAsync won't return.

TcpClient SocketException with timeout after 20s no matter what

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.

Websphere MQ isConnected variable after exception

I use an C# Console Application to put and read messages of the MQ..
When the application starts, it connect once with the MQ and then the connection should be always upholded.
The program runs every 30 sec and check if new messages are in the queue or a database(to put them on the queue) and check the isConnected-variable if its true.
But what happen if an exception(2009 - connection broke) in the Put/Get occur? Will the isConnected automatically set to false?
Is the connection automatically disconnected or do I have to call Disconnect() in the error handling?
Thanks!
To answer your exact question, for a basic .net application (non XMS) using MQQueue for put/get, if you get CERTAIN bad return codes from the underlying API call which indicates a connection issue, MQ will attempt an MQBACK and an MQDISC for you and will result in the connection handle being invalidated (IsConnected would return false) and an exception being thrown. However if an exception occurs outside those return codes then no attempt is made to do anything with the connection.
Basically you should not code an application relying on this behaviour, when the most simple answer is to always disconnect if you get an exception which relates to the quality of the connection or queue manager. For example, a no message available etc type exception doesnt mean you need to disconnect but a connection broken obviously does. There is no harm in calling disconnect on an already disconnected connection.

Wince Socket exception on asynchronous HTTP request

I am writing a WinCE app in C# that makes an HTTP POST to an APACHE server residing on my network. Because of some network issues (I am guessing), I get the following exception in the managed code
System.Net.Sockets.SocketException occurred
Message="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"
ErrorCode=10060
NativeErrorCode=10060
StackTrace:
at System.Net.Sockets.Socket.ConnectNoCheck(EndPoint remoteEP)
at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
at System.Net.Connection.doConnect(IPEndPoint ep)
at System.Net.Connection.connect(Object ignored)
at System.Threading.ThreadPool.WorkItem.doWork(Object o)
at System.Threading.Timer.ring()
This exception isn't always thrown, but when it is thrown, my app fails to connect to the server AT ALL. Repeated connection attempts don't help in reconnecting either. The only thing that helps is closing and re-deploying the app.
I can't catch the exception because its inside of managed code. Is there any way to circumvent this and close all socket connections to my server and re-initialize them? Is there something I am doing wrong?
The exception message looks a bit misleading ("connection attempt failed because the connected party") but I think it means your hardware is communicating with the server, but the server is not accepting the connection on the TCP level.
A problem I could think of is "hanging" connections, causing the server to reach the maximum number of concurrent connections and to stop accepting new ones.
Although it's just a guess, you might want to check the apache log if you can to see if you can find out if the server reports anything, and perhaps try restarting apache as soon as the problem occurs again. If that helps, you still need to find the cause of course.

TcpClient.BeginRead/TcpClient.EndRead doesn't throw exception when internet disconnected

I'm using TcpListener to accept & read from TcpClient.
The problem is that when reading from a TcpClient, TcpClient.BeginRead / TcpClient.EndRead doesn't throw exception when the internet is disconnected. It throws exception only if client's process is ended or connection is closed by server or client.
The system generally has no chance to know that connection is broken. The only reliable way to know this is to attempt to send something. When you do this, the packet is sent, then lost or bounced and your system knows that connection is no longer available, and reports the problem back to you by error code or exception (depending on environment). Reading is usually not enough cause reading only checks the state of input buffer, and doesn't send the packet to the remote side.
As far as I know, low level sockets doesn't notify you in such cases. You should provide your own time out implementation or ping the server periodically.
If you want to know about when the network status changes you can subscribe to the System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged event. This is not specific to the internet, just the local network.
EDIT
Sorry, I misunderstood. The concept of "connected" really doesn't exist the more you think about it. This post does a great job of going into more details about that. There is a Connected property on the TcpClient but MSDN says (emphasis mine):
Because the Connected property only
reflects the state of the connection
as of the most recent operation, you
should attempt to send or receive a
message to determine the current
state. After the message send fails,
this property no longer returns true.
Note that this behavior is by design.
You cannot reliably test the state of
the connection because, in the time
between the test and a send/receive,
the connection could have been lost.
Your code should assume the socket is
connected, and gracefully handle
failed transmissions.
Basically the only way to check for a client connection it to try to send data. If it goes through, you're connected. If it fails, you're not.
I don't think you'd want BeginRead and EndRead throwing exceptions as these should be use in multi threaded scenarios.
You probably need to implement some other mechanism to respond to the dropping of a connection.

Categories