Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

StreamWriter does throw exception underlying connection is broken?

I am using StreamWriter instantiated over a Tcpstream like this

streamWriter = new StreamWriter(tcpClient.GetStream());    

I am confused about the behavior of following calls with regards to Exceptions. The following two functions are expected to raise IOException Surprisingly they do not raise the IOException when the server to which the tcpClient is connected is disconnected and therefore the underlying TCP client connection is broken.. These two lines execute without raising any Exception. Why ?

streamWriter.WriteLine(strBuffer);
streamWriter.Flush();

EDIT: This particular post also helped me understand the reason, besides the replies here from the experts. http://social.msdn.microsoft.com/Forums/sk/netfxnetcom/thread/b177a935-7430-4812-9555-f747748df1af In essence the NetworkStream.Write is called when WriteLine of StreamWriter is called, This writes to the out-going buffer and returns, without blocking, unless if the buffer was full. The internal buffer maintained by OS contains unsent data, which OS will keep trying to send until a given number of attempts fail. WriteLine will throw IOException but not necessarily every time..

like image 434
Ahmed Avatar asked Jun 04 '26 15:06

Ahmed


2 Answers

This issue is unrelated to StreamWriter, it's only about the behavior of NetworkStream.

NetworkStream.Flush() is a no-op. In particular is does not block until the recipient has acknowledged all bytes sent prior to the flush.

The Flush method implements the Stream.Flush method; however, because NetworkStream is not buffered, it has no affect on network streams. Calling the Flush method does not throw an exception.

(from NetworkStream.Flush Method (MSDN))

You will get your exception at some point, but that can be much later. Essentially neither NetworkStream nor the OS know that the TCP connection is already broken, so they won't raise an exception.

like image 54
CodesInChaos Avatar answered Jun 06 '26 05:06

CodesInChaos


This is a core aspect of TCP, a protocol that promises a reliable transfer of data to another machine across a network. It is the operating system's job to ensure that the data actually ends up at the other machine. It will attempt to get the data across many times, long after you've written the data, resending IP packets if necessary if it doesn't get an acknowledgement for them. Which will be the case when you disconnected the machine. It will not give up on doing so after re-trying it many times. It can be as long as a minute before it gives up.

What is implicit in this contract that the connection is considered reliable at your end. Anything you write ends up in a buffer, located in the kernel memory pool. This buffer greatly enhances the throughput for your program, taking up the slack between your program and a variable transmission rate. Once it is in the buffer, it the operating system's duty to ensure that data actually gets sent.

You can see where this goes, you don't get an exception from a disconnect until later. It could happen on any subsequent Write() attempt, when the buffer gets too full. It may be delayed all the way to you calling the socket's Close() method.

like image 35
Hans Passant Avatar answered Jun 06 '26 06:06

Hans Passant