A
Agendum
I wrote a client / server networking application and all communication
between the two is compressed using GZipStream. However, I found a wierd
buffering problem. Despite how I had the network stream configured,
buffering would still occur (on a small scale). I pinpointed the problem to
GZipStream. Basically it seems to buffer content and calling Flush has no
effect.
Below I wrote a small sample application which demonstrates this. Basically
in two CMDs call "App.exe L" to listen, and just "App.exe" to start the
client. You will notice the GZipStream is buffering. Simply uncommenting
"//#define DONT_USE_GZIP_STREAM_READ" and "//#define
DONT_USE_GZIP_STREAM_WRITE" will cause the application to begin working. I
understand I am not getting any gain from compression here because it is just
1 byte. That is besides the point - this is just a demonstration of the
problem (the original app has sizable messages to transmit). Regardless of
size, GZipStream.Flush should flush data to the network stream and it does
not. Also, I know it is on the sending side because if I only uncomment
"//#define DONT_USE_GZIP_STREAM_READ" then every couple seconds the stream
does not read anything implying nothing was sent over the network.
How do I get this demo app to work as expected?
Thanks!
// BUGGY CODE USED FOR DEMONSTRATION ONLY
//#define DONT_USE_GZIP_STREAM_READ
//#define DONT_USE_GZIP_STREAM_WRITE
using System;
using System.IO.Compression;
using System.Net;
using System.Net.Sockets;
class Program
{
static void Main(String[] args)
{
if (args.Length > 0 && args[0] == "L")
{
TcpListener listener = new TcpListener(IPAddress.Loopback, 40);
listener.Start();
using (TcpClient client = listener.AcceptTcpClient())
{
client.NoDelay = true;
client.ReceiveBufferSize = 1;
#if DONT_USE_GZIP_STREAM_READ
NetworkStream stream = client.GetStream();
#else
GZipStream stream = new GZipStream(
client.GetStream(), CompressionMode.Decompress, false);
#endif
while (true)
{
Console.WriteLine("{0}", stream.ReadByte());
}
}
}
else
{
using (TcpClient client = new TcpClient())
{
client.Connect(IPAddress.Loopback, 40);
client.NoDelay = true;
client.SendBufferSize = 1;
#if DONT_USE_GZIP_STREAM_WRITE
NetworkStream stream = client.GetStream();
#else
GZipStream stream = new GZipStream(
client.GetStream(), CompressionMode.Compress, false);
#endif
for (Byte b = 0;; ++b)
{
stream.WriteByte(b);
stream.Flush();
Console.WriteLine("{0}", b);
System.Threading.Thread.Sleep(1000);
}
}
}
}
}
between the two is compressed using GZipStream. However, I found a wierd
buffering problem. Despite how I had the network stream configured,
buffering would still occur (on a small scale). I pinpointed the problem to
GZipStream. Basically it seems to buffer content and calling Flush has no
effect.
Below I wrote a small sample application which demonstrates this. Basically
in two CMDs call "App.exe L" to listen, and just "App.exe" to start the
client. You will notice the GZipStream is buffering. Simply uncommenting
"//#define DONT_USE_GZIP_STREAM_READ" and "//#define
DONT_USE_GZIP_STREAM_WRITE" will cause the application to begin working. I
understand I am not getting any gain from compression here because it is just
1 byte. That is besides the point - this is just a demonstration of the
problem (the original app has sizable messages to transmit). Regardless of
size, GZipStream.Flush should flush data to the network stream and it does
not. Also, I know it is on the sending side because if I only uncomment
"//#define DONT_USE_GZIP_STREAM_READ" then every couple seconds the stream
does not read anything implying nothing was sent over the network.
How do I get this demo app to work as expected?
Thanks!
// BUGGY CODE USED FOR DEMONSTRATION ONLY
//#define DONT_USE_GZIP_STREAM_READ
//#define DONT_USE_GZIP_STREAM_WRITE
using System;
using System.IO.Compression;
using System.Net;
using System.Net.Sockets;
class Program
{
static void Main(String[] args)
{
if (args.Length > 0 && args[0] == "L")
{
TcpListener listener = new TcpListener(IPAddress.Loopback, 40);
listener.Start();
using (TcpClient client = listener.AcceptTcpClient())
{
client.NoDelay = true;
client.ReceiveBufferSize = 1;
#if DONT_USE_GZIP_STREAM_READ
NetworkStream stream = client.GetStream();
#else
GZipStream stream = new GZipStream(
client.GetStream(), CompressionMode.Decompress, false);
#endif
while (true)
{
Console.WriteLine("{0}", stream.ReadByte());
}
}
}
else
{
using (TcpClient client = new TcpClient())
{
client.Connect(IPAddress.Loopback, 40);
client.NoDelay = true;
client.SendBufferSize = 1;
#if DONT_USE_GZIP_STREAM_WRITE
NetworkStream stream = client.GetStream();
#else
GZipStream stream = new GZipStream(
client.GetStream(), CompressionMode.Compress, false);
#endif
for (Byte b = 0;; ++b)
{
stream.WriteByte(b);
stream.Flush();
Console.WriteLine("{0}", b);
System.Threading.Thread.Sleep(1000);
}
}
}
}
}