Search code examples
c#tcpnetworkstreamnaudioaudiostreamer

What are the possible causes for stream not writable exception?


What are the possible causes for Stream not Writable Exception when serializing custom object over TCP using Network Stream in C#. I am Sending the Mp3 data in the form of Packets.The Frame consists of Byte[] Buffer.I am Using Binary Formatter to serialize the object.

BinaryFormatter.Serialize(NetworkStream,Packet);

The Mp3 Played at client with distortion and jitters end for few seconds and then The above mentioned exception raised.I m using NAudio Open Source library for it.

Before doing this modification I was using

NetworkStream.Write(Byte[] Buffer,0,EncodedSizeofMp3); and it was writing it successfully before giving any exception


Solution

  • If you are writing to a NetworkStream, the stream/socket could be closed

    If you are writing to a NetworkStream, it could have been created with FileAccess.Read

    If I had to guess, though, it sounds like something is closing the stream - this can be the case if, say, a "writer" along the route assumes it owns the stream, so closes the stream prematurely. It is pretty common to have to write and use some kind of wrapper Stream that ignores Close() requests (I have one in front of me right now, in fact, since I'm writing some TCP code).

    As a small aside; I generally advise against BinaryFormatter for comms (except remoting) - most importantly: it doesn't "version" in a very friendly way, but it also tends to be a bit verbose in most cases.

    Here's the wrapper I'm using currently, in case it helps (the Reset() method spoofs resetting the position, so the caller can read a relative position):

    class NonClosingNonSeekableStream : Stream
    {
        public NonClosingNonSeekableStream(Stream tail)
        {
            if(tail == null) throw new ArgumentNullException("tail");
            this.tail = tail;
        }
    
        private long position;
        private readonly Stream tail;
        public override bool CanRead
        {
            get { return tail.CanRead; }
        }
        public override bool CanWrite
        {
            get { return tail.CanWrite; }
        }
        public override bool CanSeek
        {
            get { return false; }
        }
        public override bool CanTimeout
        {
            get { return false; }
        }
        public override long Position
        {
            get { return position; }
            set { throw new NotSupportedException(); }
        }
        public override void Flush()
        {
            tail.Flush();
        }
        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }
        public override long Length
        {
            get { throw new NotSupportedException(); }
        }
        public override int Read(byte[] buffer, int offset, int count)
        {
            int read = tail.Read(buffer, offset, count);
            if (read > 0) position += read;
            return read;
        }
        public override void Write(byte[] buffer, int offset, int count)
        {
            tail.Write(buffer, offset, count);
            if (count > 0) position += count;
        }
        public override int ReadByte()
        {
            int result = tail.ReadByte();
            if (result >= 0) position++;
            return result;
        }
        public override void WriteByte(byte value)
        {
            tail.WriteByte(value);
            position++;
        }
        public void Reset()
        {
            position = 0;
        }
    }