【问题标题】:What are the possible causes for stream not writable exception?流不可写异常的可能原因是什么?
【发布时间】:2012-02-26 05:35:17
【问题描述】:

在 C# 中使用 Network Stream 通过 TCP 序列化自定义对象时,Stream not Writable Exception 的可能原因是什么。 我正在以数据包的形式发送 Mp3 数据。帧由 Byte[] 缓冲区组成。我正在使用二进制格式化程序来序列化对象。

BinaryFormatter.Serialize(NetworkStream,Packet);

Mp3 在客户端播放时出现失真和抖动几秒钟,然后出现上述异常。我正在使用 NAudio 开源库。

在做这个修改之前我正在使用

NetworkStream.Write(Byte[] Buffer,0,EncodedSizeofMp3); 并且在给出任何异常之前已经成功编写了它

【问题讨论】:

    标签: c# tcp networkstream naudio audiostreamer


    【解决方案1】:

    如果您正在写入NetworkStream,则流/套接字可能会关闭

    如果您正在写信给NetworkStream,它可能是用FileAccess.Read 创建的

    但是,如果我不得不猜测,听起来好像有什么东西正在关闭流 - 例如,如果沿途的“作家”假设它拥有流,那么就会过早地关闭流。必须编写和使用某种忽略 Close() 请求的包装器 Stream 是很常见的(事实上,因为我正在编写一些 TCP 代码,所以现在我面前有一个)。

    顺便说一句;我通常建议不要将 BinaryFormatter 用于通信(远程处理除外)- 最重要的是:它不会以非常友好的方式“版本”,但在大多数情况下它也往往有点冗长。

    这是我目前正在使用的包装器,以防万一(Reset() 方法欺骗重置位置,因此调用者可以读取 相对 位置):

    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;
        }
    }
    

    【讨论】:

    • 第二行的网络流应该是文件流吗?
    • @Chris 没有; NetworkStream 的构造函数接受一个 FileAccess 来指示流(最终只是包装一个 Socket)是否用于读/写/两者; see MSDN - 或引用:“访问参数设置 NetworkStream 的 CanRead 和 CanWrite 属性。如果指定 Write,则 NetworkStream 允许调用 Write 方法。如果指定 Read,则 NetworkStream 允许调用 Read方法。如果指定 ReadWrite,则允许两个方法调用。"
    • 在进行此修改之前,我使用的是 NetworkStream.Write(Byte[] Buffer,0,EncodedSizeofMp3);并且在给出任何异常之前已经成功编写了它
    • @Samie 所以问题变成了:在它工作和不工作之间发生了什么......?
    • @MarcGravell:啊,好的。重复它似乎是一种不寻常的语言结构,所以我认为它一定是不同的。我不得不承认我没有做过任何网络编程,所以我只是在猜测。很抱歉让您感到困惑。我保证会阅读该页面,但下次会做得更好。 ;-)
    猜你喜欢
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多