Android на компьютер FTP возобновляет загрузку странного явления - PullRequest
0 голосов
/ 15 января 2012

У меня странное явление при возобновлении передачи файла.

Посмотрите на картинку ниже, вы видите плохой раздел.

Это происходит, по-видимому, случайным образом, может быть, каждый десятый раз.
Я отправляю картинку с моего телефона Android на сервер Java через FTP.

Что я здесь забыл?
Я вижу, что соединение оборвано из-за java.net.SocketTimeoutException:
Перевод возобновляется следующим образом

Resume at : 287609 Sending 976 bytes more

Байты всегда верны, когда файл полностью получен. Даже на картинке ниже.

Не знаю, с чего начать отладку, так как она работает большую часть времени.

Любые предложения или идеи будут полезны, я думаю, что я что-то здесь полностью упустил.

enter image description here

Код отправителя устройства (только цикл отправки):

int count = 1;    
  //Sending N files, looping N times
  while(count <= max) {        
    String sPath = batchFiles.get(count-1);

    fis = new FileInputStream(new File(sPath));

    int fileSize =  bis.available();

    out.writeInt(fileSize); // size

    String nextReply = in.readUTF();
    // if the file exist,
    if(nextReply.equals(Consts.SERVER_give_me_next)){
        count++;                        
        continue;
    }
    long resumeLong = 0; // skip this many bytes 
    int val = 0;
    buffer = new byte[1024];

    if(nextReply.equals(Consts.SERVER_file_exist)){
        resumeLong = in.readLong();
    }

    //UPDATE FOR @Justin Breitfeller, Thanks
    long skiip = bis.skip(resumeLong);
if(resumeLong != -1){
   if(!(resumeLong == skiip)){
      Log.d(TAG, "ERROR skip is not the same as resumeLong ");
      skiip = bis.skip(resumeLong);
      if(!(resumeLong == skiip)){
        Log.d(TAG, "ERROR ABORTING skip is not the same as resumeLong);
        return;
      }
  }
    }

    while ((val = bis.read(buffer, 0, 1024)) > 0) {
        out.write(buffer, 0, val);
        fileSize -= val;
            if (fileSize < 1024) {
            val = (int) fileSize;
        }

    }

    reply = in.readUTF();
    if (reply.equals(Consts.SERVER_file_receieved_ok)) {
        // check if all files are sent
        if(count == max){
           break;
        }
    }
    count++;



   }

Код получателя (очень усеченный):

     //receiving N files, looping N times
    while(count < totalNrOfFiles){

        int ii = in.readInt(); // File size
        fileSize = (long)ii;

        String filePath = Consts.SERVER_DRIVE + Consts.PTPP_FILETRANSFER;
        filePath = filePath.concat(theBatch.getFileName(count));
        File path = new File(filePath);
        boolean resume = false;

        //if the file exist. Skip if done or resume if not
        if(path.exists()){
            if(path.length() == fileSize){ // Does the file has same size
                logger.info("File size same skipping file:" +                            theBatch.getFileName(count) );
                count++;
                out.writeUTF(Consts.SERVER_give_me_next);
                continue;   // file is OK don't upload it again
            }else { 
                // Resume the upload
                out.writeUTF(Consts.SERVER_file_exist); 
                out.writeLong(path.length());
                resume = true;
                fileSize = fileSize-path.length();
                logger.info("Resume at : " + path.length() + 
" Sending "+ fileSize +" bytes more");

            }
        }else
            out.writeUTF("lets go");


        byte[] buffer = new byte[1024];
        // ***********************************
        //  RECEIVE FROM PHONE
        // ***********************************

        int size = 1024;
        int val = 0;

        bos = new BufferedOutputStream(new FileOutputStream(path,resume));

        if(fileSize < size){
            size = (int) fileSize;
        }

        while (fileSize >0) {
            val = in.read(buffer, 0, size);
            bos.write(buffer, 0, val);
            fileSize -= val;
            if (fileSize < size)
                size = (int) fileSize;
        }
        bos.flush();
        bos.close();
        out.writeUTF("file received ok");

        count++;

    }

Ответы [ 2 ]

2 голосов
/ 24 января 2012

С BufferedOutputStream, BufferedInputStream, вам нужно следить за следующим

  1. Создать BufferedOutputStream до BuffererdInputStream (как на клиенте, так и на сервере)
  2. И сбрасывать сразу после создания.
  3. Сбрасывать после каждой записи (не перед закрытием)

Это сработало для меня.

Отредактировано

Добавить sentRequestTime, receiveRequestTime, sentResponseTime, receiveResponseTimeк вашему пакету полезной нагрузки.Используйте System.nanoTime () для них, запустите сервер и клиент на одном хосте, используйте ExecutorService для запуска нескольких клиентов для этого сервера и нанесите свой (получено-отправлено) для пакетов запроса и ответа, задержку времени на диаграмме Excel(некоторый формат CSV).Сделайте это до буферизованного IOStream и после IOStream.Вам будет приятно узнать, что ваша производительность повысилась на 100%.Сделал меня очень счастливым, чтобы построить этот график, заняло около 45 минут.

Я также слышал, что использование пользовательского буфера еще больше повышает производительность.

Повторное редактирование В моем случае я использую Object IOStreams, я добавил полезную нагрузку из 4 длинных переменных в объект и инициализируюsentRequestTime, когда я отправляю пакет от клиента, инициализирую receiveRequestTime, когда сервер получает ответ, и так далее, и так далее для ответа от сервера клиенту.Затем я нахожу разницу между полученным и отправленным временем, чтобы узнать задержку ответа и запроса.Будьте осторожны, чтобы запустить этот тест на локальном хосте.Если вы запускаете его между различными устройствами / устройствами, их фактическая разница во времени может повлиять на результаты вашего теста.Поскольку requestReceivedTime имеет метку времени на стороне сервера, а requestSentTime - метку времени на стороне клиента.Другими словами, их собственное местное время отпечатано (очевидно).И оба эти устройства, работающие в одно и то же время до нано секунды, невозможны.Если вам нужно запустить его между разными устройствами, по крайней мере, убедитесь, что у вас запущен ntp (чтобы синхронизировать их время).Тем не менее, вы сравниваете производительность до и после буферизации (вас действительно не волнуют фактические задержки, верно?), Поэтому смещение времени не должно иметь большого значения.Сравнение набора результатов до буферизации и после буферизации - ваш реальный интерес.

Наслаждайтесь !!!

2 голосов
/ 24 января 2012

Нашел ошибку и проблема была в плохой логике с моей стороны.не говори больше.

Я отправлял фотографии, размер которых был изменен непосредственно перед отправкой.

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

Теперь я настроил кратковременный кэш, в котором хранятся временные изображения с измененным размером.

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

...