Problems with closing TcpClient and NetworkStream
<p>currently I am working on a simple client server chat program (wanted to get into client server communication things in C#). It works so far except for disconnecting properly from the server. </p>

<p>On the client I use this code here to close the connection:</p>

<pre><code>client.Client.Disconnect(false); // client is the TcpClient
client.Close();
</code></pre>

<p>On the server there is a threaded loop waiting for messages from the client:</p>

<pre><code>private void StartChat()
{
    int requestCount = 0;
    byte[] bytesFrom = new byte[10025];
    string dataFromClient = null;
    string rCount = null;

    while (true)
    {
        try
        {
            requestCount++;

            NetworkStream stream = tcpClient.GetStream();

            int bufferSize = (int)tcpClient.ReceiveBufferSize;
            if (bufferSize &gt; bytesFrom.Length)
            {
                bufferSize = bytesFrom.Length;
            }

            stream.Read(bytesFrom, 0, bufferSize);
            dataFromClient = System.Text.Encoding.UTF8.GetString(bytesFrom);
            dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
            rCount = Convert.ToString(requestCount);

            string message = client.Name + " says: " + dataFromClient;
            program.Broadcast(message);

        }
        catch(Exception ex) when (ex is ObjectDisposedException || ex is InvalidOperationException || ex is System.IO.IOException)
        { 
            program.UserDisconnected(client);
            break;
        }
        catch(ArgumentOutOfRangeException ex)
        {
            Debug.WriteLine(ex.ToString());
            break;
        }
        catch(Exception ex)
        {
            Debug.WriteLine(ex.ToString());
            break;
        }
    }
</code></pre>

<p>If the client disconnects with the code shown above the function is fetching the stream all the time and producing such an output:</p>

<p><code>\0\0\0\0\0\0\0 [and so on]</code></p>

<p>In this case the <code>ArgumentOutOfRangeException</code> will be thrown because there is no index of <code>$</code>. I added a <code>break</code> to avoid and endless execution of the loop.</p>

<p>Surprisingly the <code>ObjectDisposedException</code> will not be thrown. Also the <code>System.IO.IOException</code> will not be thrown however it should because the stream was closed so the connection has been refused.</p>

<p>If I just close the client application which is connected to the server the server doesn't stops the loop, it just waits for a stream which will never come because the client disconnected.</p>

<p>So how could I detect if the client is disconnected or not reachable any more? And is the way I am closing the client connection a proper way to close a connection?</p>

<p>Thanks for your help!</p>

<p>Update:</p>

<pre><code>private void StartChat()
{
    int requestCount = 0;
    byte[] bytesFrom = new byte[10025];
    string dataFromClient = null;
    string rCount = null;

    while (true)
    {
        try
        {
            requestCount++;

            NetworkStream stream = tcpClient.GetStream();
            stream.ReadTimeout = 4000;

            int bufferSize = (int)tcpClient.ReceiveBufferSize;
            if (bufferSize &gt; bytesFrom.Length)
            {
                bufferSize = bytesFrom.Length;
            }


            // Wait for a client message. If no message is recieved within the ReadTimeout a IOException will be thrown
            try
            {
                int bytesRead = stream.Read(bytesFrom, 0, bufferSize);
                stream.Flush();

                if (bytesRead == 0)
                {
                    throw new System.IO.IOException("Connection seems to be refused or closed.");
                }
            }
            catch (System.IO.IOException)
            {
                byte[] ping = System.Text.Encoding.UTF8.GetBytes("%");
                stream.WriteTimeout = 1;

                stream.Write(ping, 0, ping.Length);
                continue;
            }


            dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
            dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
            rCount = Convert.ToString(requestCount);

            string message = client.Name + " says: " + dataFromClient;
            program.Broadcast(message);

        }
        catch(Exception ex) when (ex is ObjectDisposedException || ex is InvalidOperationException || ex is System.IO.IOException)
        {
            Debug.WriteLine(ex.ToString());
            program.UserDisconnected(client);
            break;
        }
        catch(ArgumentOutOfRangeException ex)
        {
            Debug.WriteLine(ex.ToString());
        }
        catch(Exception ex)
        {
            Debug.WriteLine(ex.ToString());
            break;
        }
    }
}
</code></pre>