Search code examples
javaclienttransferfreeze

my code hangs but when i debug it it never hangs


i have a java code that SOMETIMES hangs when i run it.Its a put command that puts through sockets( and input stream etc a file from a server to a client) . Sometimes this works but sometimes it doesnt and i get an error message. i tried every possible path that can be taken through debugging and i can never get it to hang. Is there a way to inspect the thing when its hang through eclipse?`

if (sentence.length() > 3 && sentence.substring(0, 3).equals("put")) {

                    File checkFile = new File(dir.getCurrentPath(), sentence.substring(4));
                    if (checkFile.isFile() && checkFile.exists()) {

                        try {
                            outToServer.writeBytes(sentence + "\n");
                            boolean cont = false;
                            String x;
                            while (!cont) {
                                if ((x = inFromServer.readLine()).equals("continue")) {
                                    cont = true;

                                }
                            }
                            String name = sentence.substring(4);
                            copy.copyFile(name);
                            //                          outToServer.writeBytes("continue" + "\n");

this is the client code that recieves the PUT request(i.e. put test.txt takes the file test.txt and puts it in the server's local dir.

Copy file: (the thing that copies the data)

File checkFile = new File(dir.getCurrentPath(), file);
    if (checkFile.isFile() && checkFile.exists()) {

        DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream());
        //              byte[] receivedData = new byte[8192];
        File inputFile = new File(dir.getCurrentPath(), file);
        byte[] receivedData = new byte[(int) inputFile.length()];
        //      String theLength = "" + inputFile.length();
        outToClient.writeBytes("" + inputFile.length() + "\n");
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(getCopyPath(file)));

        //      if (extension.equals("")) {
        //          extension = "txt";
        //      }
        //          BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //          boolean cont = false;
        //          while (!cont) {
        //              if (inFromClient.readLine().equals("continue")) {
        //                  cont = true;
        //
        //              }
        //          }
        //          outToClient.writeBytes("continue" + "\n");

        bis.read(receivedData, 0, receivedData.length);
        OutputStream os = socket.getOutputStream();
        os.write(receivedData, 0, receivedData.length);
        //          outToClient.writeBytes("finish" + "\n");
        os.flush();

Protocol on server(copies stuff in the file)

if (get.equals("put")) {
                    //so the client sends: the put request
                    //then sends the length 
                    try {
                        BufferedReader inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        DataOutputStream outToClient = new DataOutputStream(socket.getOutputStream());
                        outToClient.writeBytes("continue" + "\n");
                        int length = Integer.parseInt(inFromClient.readLine());
                        //                      String x = "";
                        //                      boolean cont = false;
                        //                      while (!cont) {
                        //                          String temp = inFromClient.readLine();
                        //                          if (temp.equals("finish")) {
                        //                              cont = true;
                        //                          }
                        //                          else {
                        //                              x += temp;
                        //                          }
                        //                      }
                        byte[] recieveFile = new byte[length];
                        InputStream is = socket.getInputStream();
                        FileOutputStream fos = new FileOutputStream("Copy " + input.substring(4));
                        BufferedOutputStream bos = new BufferedOutputStream(fos);
                        int bytesRead;
                        int current = 0;
                        bytesRead = is.read(recieveFile, 0, recieveFile.length);
                        current = bytesRead;

If you cant answer the question in specific just tell me how i can debug the code that hangs or how i can debug concurrent code.(by the way the way that the signal passing is done is by passing a token as you can see i.e. the server sents a continue token that tells the client to start sending data, i havent done this with threads methods notify and wait since i cant use , since any single object has only 1 method.


Solution

  • when your process hangs, get the current stack dump for the process. this will show you why the process is hung.

    note, you have at least one bug in your program, in that you are not handling the return value from the InputStream.read() method which will, at the very least, cause you to have busted data on the server side. (see @rk2010's answer for more details).

    you main bug, though, is that when you wrap the BufferedReader around the socket InputStream, you are probably going to end up "stealing" more bytes from the stream than the just length value. when a BufferedReader reads data from the underlying stream, it can read more data than it actually returns in the readLine() method (so, it may read 1000 chars internally, but the first "line" may only contain 20 chars). if you continue to use the BufferedReader, everything is fine, but if you discard the BufferedReader and try to read more data from the underlying stream, you will have less data there than you expect. so, when you go to read the file contents, there aren't enough bytes available.

    instead, you should be using DataOutputStream/DataInputStream exclusively. write the length as a long value (i.e. DataOutputStream.writeLong(long)), then write the bytes after (i.e. DataOutputStream.write(byte[])). then read the data using the corresponding methods in DataInputStream. since you can use the DataInputStream exclusively when reading (first to read the file size and then to read the actual file bytes), you don't risk losing bytes when switching read "modes" (additionally, DataInputStream does not do any internal buffering like BufferedReader). don't use Readers/Writers at all.