мой код зависает, но когда я отлаживаю его, он никогда не зависает - PullRequest
0 голосов
/ 23 мая 2011

У меня есть Java-код, который SOMETIMES зависает, когда я его запускаю. Это команда put, которая пропускает через сокеты (и поток ввода и т. Д. Файл с сервера на клиент).Иногда это работает, но иногда это не так, и я получаю сообщение об ошибке.Я перепробовал все возможные пути, которые могут быть приняты с помощью отладки, и я никогда не могу заставить его зависать.Есть ли способ проверить вещь, когда она зависает через 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");

это клиентский код, который получает запрос PUT (т.е. put test.txt берет файл test.txt и помещает его влокальный каталог сервера.

Копировать файл: (вещь, которая копирует данные)

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();

Протокол на сервере (копирует содержимое в файл)

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;

Если вы не можете ответить на конкретный вопрос, просто скажите мне, как я могу отлаживать зависающий код или как отлаживать параллельный код (кстати, передача сигналов осуществляется путем передачи токена, как вы можете видеть, т.е.сервер отправляет токен продолжения, который говорит клиенту начать отправку данных, я не сделал этого с помощью потоковых методов, уведомляющих и ожидающих, поскольку я не могу использовать, поскольку у любого отдельного объекта есть только 1 метод.

Ответы [ 2 ]

2 голосов
/ 23 мая 2011

когда ваш процесс зависает, получите текущий дамп стека для процесса.это покажет вам, почему процесс зависает.

обратите внимание, у вас есть хотя бы одна ошибка в вашей программе, в которой вы не обрабатываете возвращаемое значение из метода InputStream.read(), который, по крайней мере, будет, потому что вы переправили данные на стороне сервера.(подробности см. в ответе @ rk2010).

Ваша основная ошибка, однако, заключается в том, что когда вы оборачиваете BufferedReader вокруг сокета InputStream, вы, вероятно, в конечном итоге «украдете» больше байтов из потока,справедливое значение длины.когда BufferedReader считывает данные из базового потока, он может прочитать больше данных, чем фактически возвращает в методе readLine () (поэтому он может прочитать внутренне 1000 символов, но первая «строка» может содержать только 20 символов).если вы продолжаете использовать BufferedReader, все в порядке, но если вы отбросите BufferedReader и попытаетесь прочитать больше данных из базового потока, у вас будет меньше данных, чем вы ожидаете.поэтому при чтении содержимого файла недостаточно доступных байтов.

Вместо этого следует использовать исключительно DataOutputStream / DataInputStream.запишите длину как длинное значение (т.е. DataOutputStream.writeLong(long)), затем запишите байты после (т.е. DataOutputStream.write(byte[])).затем прочитайте данные, используя соответствующие методы в DataInputStream.поскольку вы можете использовать DataInputStream исключительно при чтении (сначала для чтения размера файла, а затем для чтения фактических байтов файла), вы не рискуете потерять байты при переключении режимов чтения (кроме того, DataInputStream делает не делать любую внутреннюю буферизацию, такую ​​как BufferedReader).вообще не используйте читателей / писателей.

0 голосов
/ 23 мая 2011

добавить ведение журнала после каждой команды чтения и записи. Дайте каждой теме имя. запустите программу, посмотрите, как лог соответствует тому, что вы ожидаете.

обратите внимание, что вы не всегда можете полагаться на метод чтения, такой как вы есть. Безопасный способ чтения - циклический цикл до отрицательной длины.

int len = -1;
byte[] buff = new byte[1024]; // for 4KB, use:  4* 1024

while ( (len = is.read(buff, 0, buff.length)) > -1){
  // copy len number of bytes from buff array into some other place.
}

Проверьте метод IOUtils.copy. из класса Apache Commons IOUtils

...