【问题标题】:GZipStream not send when I wantGZipStream 在我想要的时候不发送
【发布时间】:2014-08-20 11:30:10
【问题描述】:

我正在尝试通过套接字使用 GzipStream。为此,我使用了类似的东西。

using System.IO.Compression;    
TcpClient _client = null;

// ...
// ... Connection 

NetworkStream networkStream = _client.GetStream();
GZipStream zip = new GZipStream(networkStream, CompressionMode.Compress);

当我发送消息时,我使用 GZipStream 方法、Write 和 Flush:

zip.Write (....);
zip.Flush();

问题是当我运行 Flush 方法时没有发送消息。只有当我关闭 GZipStream(运行 GZipStream 类的 Close 方法)时才会发送消息。

我正在尝试这种方法:

using (GZipStream zip = new GZipStream(networkStream, CompressionMode.Compress))
{
    zip.Write (....);
}

但是,当 zip 类超出使用范围并被释放(关闭)时,networkStream 实例也被关闭和释放。

如何避免这种行为?我在实时应用程序中运行它,我需要在 GZipStream 需要时发送消息。

有什么想法吗?

谢谢。

更新:

我已经创建了一个完整的片段。

using (var client = new TcpClient("127.0.0.1", 1514))
{
    var networkStream = client.GetStream();
    client.SendBufferSize = 1;
    client.NoDelay = true;

    using (Stream zip = new GZipStream(networkStream, CompressionMode.Compress, true))
    {
        byte[] dgram = CreateMessage("Testing line 1");
        zip.Write(dgram, 0, dgram.Length);     
    }
    networkStream.Flush();

    // Next using block don't send anything. The server side does't receive anything.  
    // No exception is raised. It seems ok, but anything is sent
    using (Stream zip = new GZipStream(networkStream, CompressionMode.Compress, true))
    {
        byte[] dgram = CreateMessage("Testing line 2");
        {
            zip.Write(dgram, 0, dgram.Length);
        }
    }
    networkStream.Flush();
}

【问题讨论】:

    标签: c# .net sockets stream


    【解决方案1】:

    使用接受bool 参数的overload of the GZipStream constructor 来说明之后是否保持底层流打开:

    using (var zip = new GZipStream(networkStream, CompressionMode.Compress, true))
    {
        zip.Write (....);
    }
    

    您可能想考虑另一端了解压缩数据结束的难易程度,但是 - 我不知道这是否隐含在 gzip 流中。

    另一种方法是先写入MemoryStream,然后发送(压缩的)长度,然后发送压缩数据......然后另一端可以读取长度,读取那么多数据,解压缩它,然后准备好之后阅读下一条消息。

    【讨论】:

    • 谢谢。但是,如果我运行 using 块(根据您的建议)两次或更多次,则只能在第一次运行。第二次没有触发异常。似乎工作正常,但服务器端没有收到任何东西。
    • @user2499597:这并没有真正提供有关发生了什么的详细信息。您应该使用 Wireshark 查看行为,以了解网络上发生了什么。之后您还应该刷新网络流。
    • Flush 方法不能像我们希望的那样对 GZipStream 起作用。
    • @user2499597:我是说你应该刷新 network 流(在 dispose 之后)。基本上,你仍然需要提供更多细节。
    • 感谢您的时间@Jon Skeet。我照你说的做了。关闭 GZipStream 和后来的 Flush NetworkStream 但它不能正常工作。哪些细节有助于理解这个问题?谢谢
    【解决方案2】:

    使用带有布尔值的GZipStream constructor 来确定是否保持底层流打开:

    GZipStream 构造函数(Stream、CompressionLevel、Boolean)

    使用指定的流和压缩级别初始化 GZipStream 类的新实例,并可选择保持流打开。

    using (GZipStream zip = new GZipStream(networkStream, CompressionMode.Compress, true))
    {
        zip.Write (....);
    }
    

    【讨论】:

    • 谢谢。但是,如果我运行 using 块(根据您的建议)两次或更多次,则只能在第一次运行。第二次没有触发异常。似乎工作正常,但服务器端没有收到任何东西。
    猜你喜欢
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    相关资源
    最近更新 更多