Name: nt126004 Date: 11/19/2001 java version "1.4.0-beta3" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta3-b84) Java HotSpot(TM) Client VM (build 1.4.0-beta3-b84, mixed mode) We have run into problems trying to implement compression across sockets between a Java client and a C++ server. To isolate the problems we have created a simple Java client and server. The client reads from standard input a sends data to the server line by line. The server merely echoes the client's input. Client.java: ================================================================================ import java.io.*; import java.net.Socket; import java.util.zip.*; public class Client { public static void main(String[] args) { boolean nowrap = true; if (args.length == 1 && args[0].equals("-h")) nowrap = false; try { Client client = new Client(nowrap); client.test(); } catch (IOException ex) { ex.printStackTrace(); } } private Socket socket; private Inflater inflater; private InflaterInputStream iIn; private DataInputStream in; private Deflater deflater; private DeflaterOutputStream dOut; private DataOutputStream out; public Client(boolean nowrap) throws IOException { this.socket = new Socket("127.0.0.1", 3000); this.inflater = new Inflater(nowrap); this.iIn = new InflaterInputStream(socket.getInputStream(), inflater); this.in = new DataInputStream(iIn); this.deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, nowrap); this.dOut = new DeflaterOutputStream(new BufferedOutputStream (socket.getOutputStream()), deflater); this.out = new DataOutputStream(dOut); } public void test() throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader (System.in)); String line; while ((line = reader.readLine()) != null) { System.out.print("Writing... "); out.writeUTF(line); dOut.finish(); out.flush(); deflater.reset(); System.out.println(line); System.out.print("Reading... "); String result = in.readUTF(); inflater.reset(); System.out.println(result); } socket.close(); System.out.println("Disconnected."); } } ================================================================================ Server.java ================================================================================ import java.io.*; import java.net.*; import java.util.zip.*; public class Server { public static void main(String[] args) { boolean nowrap = true; if (args.length == 1 && args[0].equals("-h")) nowrap = false; try { Server server = new Server(nowrap); server.test(); } catch (IOException ex) { ex.printStackTrace(); } } private ServerSocket serverSocket; private Socket socket; private Inflater inflater; private InflaterInputStream iIn; private DataInputStream in; private Deflater deflater; private DeflaterOutputStream dOut; private DataOutputStream out; public Server(boolean nowrap) throws IOException { System.out.print("Waiting for connection... "); this.serverSocket = new ServerSocket(3000); this.socket = serverSocket.accept(); System.out.println("Done."); this.inflater = new Inflater(nowrap); this.iIn = new InflaterInputStream(socket.getInputStream(), inflater); this.in = new DataInputStream(iIn); this.deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, nowrap); this.dOut = new DeflaterOutputStream(new BufferedOutputStream (socket.getOutputStream()), deflater); this.out = new DataOutputStream(dOut); } public void test() throws IOException { while (true) { try { System.out.print("Reading... "); String result = in.readUTF(); inflater.reset(); System.out.println(result); System.out.print("Writing... "); out.writeUTF(result); dOut.finish(); out.flush(); deflater.reset(); System.out.println(result); } catch (EOFException ex) { break; } } socket.close(); System.out.println("Disconnected."); } } ================================================================================ The client and server work fine for most input, however certain input can cause either the client or the server to fail consistently with an exception similar to the following: java.util.zip.ZipException: unknown compression method at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:139) at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:104) at java.io.DataInputStream.readUnsignedShort(DataInputStream.java:290) at java.io.DataInputStream.readUTF(DataInputStream.java:519) at java.io.DataInputStream.readUTF(DataInputStream.java:496) at Server.test(Server.java:44) at Server.main(Server.java:12) With the default buffer size for InflaterInputStream and DeflaterOutputStream (512 bytes) and ZLib headers enabled (using the -h option to both Client and Server), the following input will trigger the exception: in.txt ================================================================================ wfwuwwakwrktgfxivdodjbtfsgbcidftcapyzvzwbzlgprqgxiqivdqbgxiaowtfmvlxbqrrcfbmxomi xpejsobwfiltinuzszgxjtykyepjhpiqwihqmzmeluxruqmdvbkilbjyeqsbeycsjlwxbywocwviifzi otamzpqwbwlgzpujcjsyefatcxmqjemkkztqicosbbcuvncmfbvidxqrdznvlaxchsyzzkalsbgzsgdn lmaxlincicnvgarnnegrixiighvoxphodbmsmmsxnnbzhoukhbxrxprbminffiltdgsqyyvetzoramjo bxzojlgpgarqnhkvfgskmuigvzbdbmeforzwombyzaxniqilrsfwuafsviewcopyhsnmmdutmhlqrnrz zifhbckkucantvmeeddnisasjfqwrzphzftbyjwblmrycffugqavjtgfmrpzrllxaawqslivqxwctcyb pwgajsolssrpezegbdqyeaiirvxznndarqutudpocfryeftnuspetngclvzqlzsrdsspprencebogpri hdmwrgqhzqhfmnbvwbaimofkryjdihyfhvppogrwtiibpjodhmlfjgzwxycqoeefracfwppxhgahxqzd ctrqxgiyrqopncbuifgojdajsjxzcjurplwotczmypjaugqfoyjxdaltzfevdmkssxvtbdmrwmoctedl hcaaquywapmqwtpodbjyxfogcdzkkwjouofmfsgregwphiqogqgwognwalhouvmpmgzxiohauonupvuz k ================================================================================ (Note that this input consists of one line of 802 characters and one blank line. The first line is the cause, but the exception is thrown when trying to read the following line.) For other buffer sizes, other input can be found that triggers the failure (try any large file with lots of long lines, or use Test.java below to generate one). The exception seems to occur when the compressed size of the line of input is a few bytes more than the InflaterInputStream buffer. There seems to be some sort of off-by-one error or buffer overflow happening, but as the bulk of the inflation/deflation is in native code I am unable to track it down. Please help. Test.java (generates a large input file to use on the client) ================================================================================ import java.io.*; import java.util.Random; public class Test { public static void main(String[] args) { PrintStream out = new PrintStream(new BufferedOutputStream (System.out)); Random random = new Random(); for (int i = 1; i < 2000; i++) { for (int j = 1; j <= i; j++) { char c = (char)('a' + random.nextInt(26)); out.print(c); } out.println(); } } } ================================================================================ (Review ID: 135062) ======================================================================
|