Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4206909

want java.util.zip to work for interactive use (Z_SYNC_FLUSH)

    Details

    • Type: Enhancement
    • Status: Closed
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 1.1.7, 1.1.8, 1.2.0, 1.3.0, 1.4.2
    • Fix Version/s: 7
    • Component/s: tools
    • Subcomponent:
      jar
    • Resolved In Build:
      b77
    • CPU:
      generic, x86
    • OS:
      generic, windows_98, windows_nt
    • Verification:
      Verified

      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)
      ======================================================================

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                sherman Xueming Shen
                Reporter:
                zlisunw Zhenghua Li (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: