title: Socket not registering when the other end is closed
body: <p>I'm working on a client/server application where the connections from the client to the server stay open until the client application is closed.</p>
  
  <p>If the server application goes down unexpectedly, while the client is reading data, I want the client to treat this as an exception, but then to catch the exception and raise an event with the exception as the argument.</p>
  
  <p>I've written a test that I think should test that this system works, but the object I'm testing doesn't seem to register that the socket is closed unless I put in a break point and then continue.</p>
  
  <p>The important part of the test looks like this:</p>
  
  <pre><code>StreamingMonitor sm = new StreamingMonitor();
  bool errored = false;
  string msg = "";
  sm.ErrorOccurred += (s, a) =&gt;
  {
      errored = true;
      msg = a.Exception.Message;
  };
  sm.Enabled = true;
  client = listener.AcceptTcpClient();
  client.GetStream().Write(BitConverter.GetBytes(10000), 0, 4);
  client.Close();
  while(!errored)
  {}
  Assert.AreEqual("A request to send or receive data was disallowed because the socket had already been shut down in that direction with a previous shutdown call", msg);
  </code></pre>
  
  <p>The <code>TcpListener</code> object <code>listener</code> is listening to the loopback address.</p>
  
  <p>The <code>StreamingMonitor</code> begins listening for the length of the data to retrieve when it is enabled. The length of data is always assumed to fit into a signed 32 bit integer.</p>
  
  <p>When the message length is received then this methods is called.</p>
  
  <pre><code>    private void GotMessageLength(IAsyncResult asyncResult)
      {
          try
          {
              client.Client.EndReceive(asyncResult);
              if(firstMessage)
              {
                  firstMessage = false;
                  if (Connected != null)
                  {
                      Connected(this, new EventArgs());
                  }
              }
              int msgLen = BitConverter.ToInt32(messageLength, 0);
              byte[] message = new byte[msgLen];
              List&lt;byte&gt; lbMessage = new List&lt;byte&gt;();
              int bytesReturned = client.Client.Receive(message);
              int remaining = (msgLen &lt; bytesReturned) ? bytesReturned - msgLen : msgLen - bytesReturned;
              if(remaining &gt; 0)
              {
                  if (bytesReturned &gt; 0)
                  {
                      for (int i = 0; i &lt; bytesReturned; i++)
                      {
                          lbMessage.Add(message[i]);
                      }
                  }
                  while(remaining &gt; 0)
                  {
                      if(!client.Connected)
                      {
                          throw new SocketException((int)SocketError.Shutdown);
                      }
                      bytesReturned = client.Client.Receive(message);
                      remaining = (remaining &lt; bytesReturned) ? bytesReturned - remaining : remaining - bytesReturned;
                      if (bytesReturned &gt; 0)
                      {
                          for (int i = 0; i &lt; bytesReturned; i++)
                          {
                              lbMessage.Add(message[i]);
                          }
                      }
                  }
                  message = lbMessage.ToArray();
              }
              MessageReceived(this, new MessageReceivedEventArgs(message));
              if (Enabled)
              {
                  client.Client.BeginReceive(messageLength, 0, 4, SocketFlags.None, GotMessageLength, null);
              }
          }
          catch (SocketException ex)
          {
              if(ErrorOccurred != null)
              {
                  ErrorOccurred(this, new ErrorEventArgs(ex));
              }
          }
          catch (ObjectDisposedException)
          {
  
          }
      }
  </code></pre>
  
  <p>The method reads data from the network stream until it has read the specified number of bytes. If the remote connection closes then it should raise a socket exception.</p>
  
  <p>However, the unit test gets caught in a infinite loop, waiting for the error to occur, because the socket in the <code>StreamingMonitor</code> never realises that the other end has closed.</p>
  
  <p>How can I make the <code>SteamingMonitor</code> realise that the server has gone?</p>
  
  <p>Is this possible on the loopback address?</p>
  
  <p>Sorry for all the code, I couldn't think how to cut the method down.</p>