NetworkStream gets System.IO.IOException: Unable to write data to the transport connection

Tim picture Tim · Apr 3, 2018 · Viewed 9.7k times · Source

I am using a NetworkStream to keep an open TCP/IP connection that messages can be sent across. I receive a message, process it, and then return an ACK. I am working with a site where occasionally I receive the message, but when I go to send the ACK, I get an IOException. Sometimes this lasts for only one or two messages (I can receive the next message), and other times it continues until the service is stopped and restarted.

Below is the code for my NetworkStream without any of the processing:

using (NetworkStream stream = client.GetStream())
{
   stream.ReadTimeout = ReadTimeout;
...
   if (stream.CanRead && stream.DataAvailable)
   bytesRead = stream.Read(receivedBytes, 0, BufferSize);
...
   stream.Write(ack, 0, ack.Length);
}

Note that the code loops between reading new messages and sending the ACK.

When I call stream.Write, I will sometimes get the following exception:

System.IO.IOException: Unable to write data to the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine
   at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at Framework.Communication.Model.Server.AcceptMessage(IAsyncResult ar)

I have looked this message up and found several sources for it for several different communication methods. It sounds like this is a very generic exception that does not really tell what is happening.

Does anyone know what would cause this, or where I could start looking to narrow down the solution?

Answer

TheGeneral picture TheGeneral · Apr 3, 2018

You are right to think this is a generic problem, so you will have to be more defensive.

Somethings to consider

  1. When an application closes a socket the right way, it sends a message containing 0 bytes.
  2. In some cases you may get a SocketException indicating something went wrong.
  3. In a third situation, the remote party is no longer connected (for instance by unplugging the network cable) without any communication between the two parties.

    • If this happens, you'll have to write data to the socket in order to detect that you can no longer reach the remote party. This is why keep-alive mechanisms were invented - they check every so often whether they can still communicate with the other side.

Note : None of this explains the intermittent nature of part of the question (if i'm reading it correctly)


So lets see what the documentation says

NetworkStream.Write Method (Byte[], Int32, Int32)

IOException

  • There was a failure while writing to the network.
  • An error occurred when accessing the socket. See the Remarks section for more information.

Remarks

If you receive a SocketException, use the SocketException.ErrorCode property to obtain the specific error code, and refer to the Windows Sockets version 2 API error code documentation in MSDN for a detailed description of the error.


So in my mind, as mentioned before you need to be a bit more defensive.

  1. Check for 0 bytes.

  2. Check for errors.

    • I you get an error make sure you are checking the error codes

In either of these cases, its probably good practice (and makes sense) to restart the connection again, log the failure, and assume the connection has been closed (or abnormally closed)


Additional resources

Detect closed network connection

**** Detection of Half-Open (Dropped) Connections **** Stephen Cleary