title: Sending and receiving over network using TcpClient (socket or Stream) fails after X interactions
body: <p>I have a couple very simple socket programs to do length-prefixed string sending and receiving.  Here's the core routines:</p>
  
  <pre><code>// Send a string, length-prefixed, to a socket.
  public static void SendStringToSocket(Socket socket, string str)
  {
      byte[] dataBuffer = Encoding.UTF8.GetBytes(str);
      Console.WriteLine("SendStringToSocket: " + dataBuffer.Length);
      byte[] lengthBuffer = LengthToNetworkBytes(dataBuffer.Length);
      byte[] overallBuffer = new byte[dataBuffer.Length + lengthBuffer.Length];
  
      for (int b = 0; b &lt; lengthBuffer.Length; ++b)
          overallBuffer[b] = lengthBuffer[b];
  
      for (int d = 0; d &lt; dataBuffer.Length; ++d)
          overallBuffer[d + lengthBuffer.Length] = dataBuffer[d];
  
      Console.WriteLine("SendStringToSocket: Sending " + overallBuffer.Length);
      socket.Send(overallBuffer);
      Console.WriteLine("SendStringToSocket: Complete");
  }
  
  // Read a length-prefixed string from a socket.
  public static string ReadStringFromSocket(Socket socket)
  {
      byte[] buffer = new byte[8192];
      bool bReadLength = false;
      int nStrLen = -1;
      MemoryStream memStream = new MemoryStream(buffer.Length);
      while (true)
      {
          Console.WriteLine("ReadStringFromSocket: Reading...");
          int nRead = socket.Receive(buffer, SocketFlags.None);
          if (nRead == 0)
              break;
  
          int nOffset = 0;
          if (!bReadLength)
          {
              byte[] lenBuffer = new byte[sizeof(int)];
              if (nRead &lt; lenBuffer.Length)
                  throw new RuntimeException(ErrorCode.NetworkError, "Reading string length failed.");
  
              for (int b = 0; b &lt; lenBuffer.Length; ++b)
                  lenBuffer[b] = buffer[b];
  
              nStrLen = NetworkBytesToLength(lenBuffer);
              Console.WriteLine("ReadStringFromSocket: Length: " + nStrLen);
              if (nStrLen &lt; 0)
                  throw new RuntimeException(ErrorCode.NetworkError, "Invalid string length: " + nStrLen + " - be sure to convert from host to network");
  
              bReadLength = true;
              nOffset = lenBuffer.Length;
  
              if (nStrLen == 0)
              {
                  Console.WriteLine("ReadStringFromSocket: Complete with no length");
                  if (nRead != lenBuffer.Length)
                      throw new RuntimeException(ErrorCode.NetworkError, "Zero length string has more data sent than expected.");
                  return "";
              }
          }
  
          memStream.Write(buffer, nOffset, nRead - nOffset);
  
          if (memStream.Length &gt; nStrLen)
              throw new RuntimeException(ErrorCode.NetworkError, "More string data sent than expected.");
  
          if (memStream.Length == nStrLen)
              break;
      }
  
      Console.WriteLine("ReadStringFromSocket: Complete with " + memStream.Length + " bytes");
      return Encoding.UTF8.GetString(memStream.GetBuffer(), 0, (int)memStream.Length);
  }
  </code></pre>
  
  <p>I think these routines embody the best practices for this sort of thing.</p>
  
  <p>Here's the client app:</p>
  
  <pre><code>static void Main(string[] args)
  {
      if (args.Length != 2)
      {
          Console.WriteLine("StringSocketClient &lt;server address&gt; &lt;server port&gt;");
          return;
      }
  
      TcpClient client = new TcpClient(args[0], int.Parse(args[1]));
      Socket socket = client.Client;
  
      while (true)
      {
          Console.Write("&gt; ");
  
          string strInput = Console.ReadLine();
  
          Console.WriteLine("Sending...");
          Utils.SendStringToSocket(socket, strInput);
  
          Console.WriteLine("Receiving...");
          string strResponse = Utils.ReadStringFromSocket(socket);
  
          Console.WriteLine("Response:");
          Console.WriteLine(strResponse);
          Console.WriteLine();
      }
  }
  </code></pre>
  
  <p>Here's the server app:</p>
  
  <pre><code>static void Main(string[] args)
  {
      if (args.Length != 1)
      {
          Console.WriteLine("StringSocketEchoServer &lt;TCP port to serve&gt;");
          return;
      }
  
      TcpListener listener = new TcpListener(IPAddress.Any, int.Parse(args[0]));
      listener.Start();
      while (true)
      {
          TcpClient client = listener.AcceptTcpClient();
          new Thread(ProcessConnection).Start(client);
      }
  }
  
  static void ProcessConnection(object state)
  {
      TcpClient client = (TcpClient)state;
      Socket socket = client.Client;
  
      try
      {
          while (true)
          {
              Console.WriteLine("Reading from network...");
              string str = Utils.ReadStringFromSocket(socket);
              Console.WriteLine("Received: " + str);
  
              Console.WriteLine("Sending back...");
              Utils.SendStringToSocket(socket, str);
          }
      }
      catch (Exception exp)
      {
          Console.WriteLine("EXCEPTION!\r\n" + exp);
          try
          {
              client.Close();
              client = null;
          }
          catch { }
      }
  }
  </code></pre>
  
  <p>Real straightforward, simple stuff, cut down to the bone of the problem.</p>
  
  <p>What I'm finding is that if I do five interactions, the client hangs trying to receive a response, and the server is trying to receive a request.  Here's the console outputs:</p>
  
  <p>Client:</p>
  
  <blockquote>
    <p>foobar
        Sending...
        SendStringToSocket: 6
        SendStringToSocket: Sending 10
        SendStringToSocket: Complete
        Receiving...
        ReadStringFromSocket: Reading...
        ReadStringFromSocket: Length: 6
        ReadStringFromSocket: Complete with 6 bytes
        Response:
        foobar</p>
  </blockquote>
  
  <pre><code>&gt; foobar
  Sending...
  SendStringToSocket: 6
  SendStringToSocket: Sending 10
  SendStringToSocket: Complete
  Receiving...
  ReadStringFromSocket: Reading...
  ReadStringFromSocket: Length: 6
  ReadStringFromSocket: Complete with 6 bytes
  Response:
  foobar
  
  &gt; foobar
  Sending...
  SendStringToSocket: 6
  SendStringToSocket: Sending 10
  SendStringToSocket: Complete
  Receiving...
  ReadStringFromSocket: Reading...
  ReadStringFromSocket: Length: 6
  ReadStringFromSocket: Complete with 6 bytes
  Response:
  foobar
  
  &gt; foobar
  Sending...
  SendStringToSocket: 6
  SendStringToSocket: Sending 10
  SendStringToSocket: Complete
  Receiving...
  ReadStringFromSocket: Reading...
  ReadStringFromSocket: Length: 6
  ReadStringFromSocket: Complete with 6 bytes
  Response:
  foobar
  
  &gt; foobar
  Sending...
  SendStringToSocket: 6
  SendStringToSocket: Sending 10
  SendStringToSocket: Complete
  Receiving...
  ReadStringFromSocket: Reading...
  ^CPress any key to continue . . .
  </code></pre>
  
  <p>Server:</p>
  
  <pre><code>Reading from network...
  ReadStringFromSocket: Reading...
  Reading from network...
  ReadStringFromSocket: Reading...
  ReadStringFromSocket: Length: 6
  ReadStringFromSocket: Complete with 6 bytes
  Received: foobar
  Sending back...
  SendStringToSocket: 6
  SendStringToSocket: Sending 10
  SendStringToSocket: Complete
  Reading from network...
  ReadStringFromSocket: Reading...
  ReadStringFromSocket: Length: 6
  ReadStringFromSocket: Complete with 6 bytes
  Received: foobar
  Sending back...
  SendStringToSocket: 6
  SendStringToSocket: Sending 10
  SendStringToSocket: Complete
  Reading from network...
  ReadStringFromSocket: Reading...
  ReadStringFromSocket: Length: 6
  ReadStringFromSocket: Complete with 6 bytes
  Received: foobar
  Sending back...
  SendStringToSocket: 6
  SendStringToSocket: Sending 10
  SendStringToSocket: Complete
  Reading from network...
  ReadStringFromSocket: Reading...
  ReadStringFromSocket: Length: 6
  ReadStringFromSocket: Complete with 6 bytes
  Received: foobar
  Sending back...
  SendStringToSocket: 6
  SendStringToSocket: Sending 10
  SendStringToSocket: Complete
  Reading from network...
  ReadStringFromSocket: Reading...
  </code></pre>
  
  <p>Earlier in the day, it was three interactions then the hang.</p>
  
  <p>I think the code's correct.  It works X times.  But then it hangs.</p>
  
  <p>Any ideas?</p>