JDK-4206909 : want java.util.zip to work for interactive use (Z_SYNC_FLUSH)
  • Type: Enhancement
  • Component: tools
  • Sub-Component: jar
  • Affected Version: 1.1.7,1.1.8,1.2.0,1.3.0,1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,windows_98,windows_nt
  • CPU: generic,x86
  • Submitted: 1999-01-28
  • Updated: 2017-05-16
  • Resolved: 2012-01-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b77Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Description

Name: zl72593			Date: 01/28/99

=20
To establish an encrypted network connection for _interactive_
use you need to compress the stream _before_ encryption because
an already encrypted stream is not compressible.

Today it is not possible to reuse java.util.zip for compression
because the Java VM calls deflate() in the libz with
Z_NO_FLUSH (and Z_FINISH for EOF) only. This means that in most
cases the deflate() does not emit enough data for the
decompressor to reassemble the complete data packet because
it waits for more input.

This is what the deflate() parameter Z_SYNC_FLUSH is for.
It enables the inflate() of the receiver to create the full
data packet. This will decrease the compression ration slightly=20
but will allow to reuse java.util.zip for interactive use.

Please note that this is _not_ Z_FULL_FLUSH, which would tell
deflate() to do a full reset of the compressor.
(Review ID: 52795)
======================================================================

Name: krT82822			Date: 10/29/99


N/A API deficiency
The java.util.zip routines do not support the zlib functionality of
Z_SYNC_FLUSH. This makes it impossible to write a client-server application
where the client and server pass each other messages along a compressed stream,
as you need to be able to compress a message (given the current dictionary, not
just starting with a new one), flush and byte-align the output, and then send
the message across the socket. This is possibile with the c implemention of
zlib, as the Z_SYNC_FLUSH will flush and byte-align the output of the current
compression operation.
(Review ID: 97225)
======================================================================

Name: mc57594			Date: 01/05/2000


C:\>java -version
java version "1.2"
Classic VM (build JDK-1.2-V, native threads)


I am trying to develop a client/server application using sockets. To improve
performance I am trying to zip de data sent to the socket, using
java.util.zip.DeflaterOutputStream and java.util.zip.inflaterInputStream, but
the application stops when the client or the server write something in the
output stream.

Without zip stream it works fine.

Here is the code of client:

import java.net.*;
import java.io.*;
import java.util.zip.*;

public class SocketClientApp
{
  public static void main( String [] args ) throws IOException
  {
    Socket clientSocket = null;
    PrintWriter out     = null;
    BufferedReader in   = null;

    try
    {
      clientSocket = new Socket( "localhost", 4444 );
      out = new PrintWriter( new DeflaterOutputStream(
                                 clientSocket.getOutputStream() ), true );
      in  = new BufferedReader( new InputStreamReader( new InflaterInputStream(
                                 clientSocket.getInputStream() ) ) );

      BufferedReader stdIn = new BufferedReader( new InputStreamReader(
                                                               System.in ) );

      String fromServer, fromUser;
      while( ( fromServer = in.readLine() ) != null )
      {
        System.out.println( "Server said: " + fromServer );
        fromUser = stdIn.readLine();
        if( fromUser != null )
          out.println( fromUser );

        if( fromUser.equals( "TChau!" ) )
          break;
      }

      out.close();
      in.close();
      stdIn.close();
      clientSocket.close();
    }
    catch( UnknownHostException e)
    {
      e.printStackTrace();
    }
    catch( IOException e )
    {
      e.printStackTrace();
    }
  }
}

Here is the code of the server Thread:

import java.net.*;
import java.io.*;
import java.util.zip.*;

public class SocketServerThread extends Thread
{
   private Socket clientSocket;

   public SocketServerThread( Socket clientSocket )
   {
      super( "MultiServerThread" );

      this.clientSocket = clientSocket;
   }

   public void run()
   {
      try
      {
         PrintWriter out   = new PrintWriter( new DeflaterOutputStream(
                                      clientSocket.getOutputStream() ), true );
         BufferedReader in = new BufferedReader( new InputStreamReader( new
InflaterInputStream( clientSocket.getInputStream() ) ) );

         String inputLine, outputLine;

         outputLine = "Server: Hello!";
         out.println( outputLine );

         while( ( inputLine = in.readLine() ) != null )
         {
            System.out.println( "Received: " + inputLine );
            if( inputLine.equals( "TChau!" ) )
              break;
            outputLine = "You typed: " + inputLine;
            out.println( outputLine );
         }

         in.close();
         out.close();
         clientSocket.close();
      }
      catch( IOException e )
      {
         e.printStackTrace();
      }
   }
}

Here is the server application:

import java.net.*;
import java.io.*;

public class MultiSocketServerApp
{
   static public void main( String [] args ) throws IOException
   {
      ServerSocket serverSocket = null;
      try
      {
        serverSocket = new ServerSocket( 4444 );
      }
      catch( IOException e )
      {
        e.printStackTrace();
      }

      while( true )
      {
        Socket clientSocket = null;
        try
        {
           clientSocket = serverSocket.accept();
           SocketServerThread newThread = new SocketServerThread(
clientSocket );
           newThread.start();
        }
        catch( IOException e )
        {
           e.printStackTrace();
           System.exit(-1);
        }
      }
   }
}
(Review ID: 98981)
======================================================================

Name: krC82822			Date: 01/27/2001


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

There is no way to do a partial or sync flush of java.util.zip.Deflater. A
partial flush is required when you want to send multiple compressed segments on
a single stream such that they use the same compression parameters and
dictionary. In particular, it is needed to properly implement the compression
mode of Secure Shell.

Add a deflate() method with the following signature:
  public synchronized int deflate( byte[] b, int off, int len, int flush );

where flush is one of
  public static final int DEFLATER_NO_FLUSH      = 0;
  public static final int DEFLATER_PARTIAL_FLUSH = 1;
  public static final int DEFLATER_SYNC_FLUSH    = 2;
  public static final int DEFLATER_FULL_FLUSH    = 3;
  public static final int DEFLATER_FINISH        = 4;

You can make this change without breaking any existing code: when Deflater's
private field 'finish' is true, the existing deflate() methods should call the
new method with a flush argument of DEFLATER_FINISH. Otherwise they would
specify DEFLATER_NO_FLUSH.

It's actually a bit more complicated than that. If the caller supplies
DEFLATER_FINISH, you would have to call end() to update the 'finish' field.
(Review ID: 115912)
======================================================================

Comments
EVALUATION A flush with Z_SYNC_FLUSH is all we need.
20-02-2009

WORK AROUND Name: zl72593 Date: 01/28/99 =20 Port a compressor/decompressor to Java and use that instead of java.util.zip. To avoid porting to several platforms this must be done in 100% Java which will decrease the compressor speed. ======================================================================
11-09-2004