using System.IO; using System.Net.Sockets; public static class NetworkStreamExtensions { // .Read returns '0' if remote closed the connection but throws an // IOException if we voluntarily closed our own connection. // // lets's add a ReadSafely method that returns '0' in both cases so we don't // have to worry about exceptions, since a disconnect is a disconnect... public static int ReadSafely(this NetworkStream stream, byte[] buffer, int offset, int size) { try { return stream.Read(buffer, offset, size); } catch (IOException) { return 0; } } // helper function to read EXACTLY 'n' bytes // -> default .Read reads up to 'n' bytes. this function reads exactly 'n' // bytes // -> this is blocking until 'n' bytes were received // -> immediately returns false in case of disconnects public static bool ReadExactly(this NetworkStream stream, byte[] buffer, int amount) { // there might not be enough bytes in the TCP buffer for .Read to read // the whole amount at once, so we need to keep trying until we have all // the bytes (blocking) // // note: this just is a faster version of reading one after another: // for (int i = 0; i < amount; ++i) // if (stream.Read(buffer, i, 1) == 0) // return false; // return true; int bytesRead = 0; while (bytesRead < amount) { // read up to 'remaining' bytes with the 'safe' read extension int remaining = amount - bytesRead; int result = stream.ReadSafely(buffer, bytesRead, remaining); // .Read returns 0 if disconnected if (result == 0) return false; // otherwise add to bytes read bytesRead += result; } return true; } }