Pregunta

Tengo un fenómeno extraño al reanudar la transferencia de un archivo.

Mira la imagen de abajo para ver la sección mala.

Esto sucede aparentemente al azar, tal vez cada décima vez.
Estoy enviando la imagen desde mi teléfono Android al servidor Java a través de ftp.

¿Qué es lo que olvidé aquí?
Veo que la conexión se interrumpe debido a java.net.SocketTimeoutException:
La transferencia se reanuda así

Resume at : 287609 Sending 976 bytes more

Los bytes siempre son correctos cuando el archivo se recibe por completo. Incluso para la imagen de abajo.

No sé por dónde empezar a depurar esto, ya que funciona la mayoría de las veces.

Cualquier sugerencia o idea sería agradecida, creo que me perdí algo aquí.

ingrese la descripción de la imagen aquí

El código del remitente del dispositivo (solo enviar bucle):

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++;



   }

El código del receptor (muy truncado):

     //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++;

    }
¿Fue útil?

Solución

Encontré el error y el problema fue una mala lógica de mi parte. no digas más.

Estaba enviando imágenes cuyo tamaño estaba cambiando justo antes de que se enviaran.

El problema fue cuando se inició el currículum después de una transferencia fallida
la imagen redimensionada no se usó, en su lugar, el código usó el original
en la foto que tenía un tamaño de escala mayor.

Ahora he configurado un caché de corta duración que contiene las imágenes temporales redimensionadas.

A la luz de la complejidad de la aplicación que estoy creando, simplemente olvidé que los archivos durante el resumen no eran los mismos que los originales.

Otros consejos

Con BufferedOutputStream, BufferedInputStream, debe tener cuidado con lo siguiente

  1. Cree BufferedOutputStream antes de BuffererdInputStream (tanto en el cliente como en el servidor)
  2. Y descargue justo después de crear.
  3. Vaciar después de cada escritura (no solo antes del cierre)

Eso funcionó para mí.

Editado

Agregue sentRequestTime ,ivedRequestTime, sentResponseTime ,ivedResponseTime a la carga útil de su paquete. Use System.nanoTime () en estos, ejecute su servidor y cliente en el mismo host, use ExecutorService para ejecutar múltiples clientes para ese servidor y trazar su (recibido-enviado) para los paquetes de solicitud y respuesta, el tiempo de retraso en un gráfico de Excel (algún formato csv). Haga esto antes de bufferIOStream y afterIOStream. Le complacerá saber que su rendimiento ha aumentado en un 100%. Me hizo muy feliz trazar ese gráfico, tomó unos 45 minutos.

También escuché que el uso de búfer personalizados mejora aún más el rendimiento.

Editado de nuevo En mi caso, estoy usando Object IOStreams, agregué una carga útil de 4 variables largas al objeto e inicializo sentRequestTime cuando envío el paquete desde el cliente, inicializoivedRequestTime cuando el servidor recibe la respuesta, y así sucesivamente para la respuesta también del servidor al cliente. Luego encuentro la diferencia entre el tiempo recibido y enviado para averiguar el retraso en la respuesta y la solicitud. Tenga cuidado de ejecutar esta prueba en localhost. Si lo ejecuta entre diferentes dispositivos / hardware, su diferencia de tiempo real puede interferir con los resultados de su prueba. Dado que requestReceivedTime tiene una marca de tiempo en el extremo del servidor y requestSentTime tiene una marca de tiempo en el extremo del cliente. En otras palabras, su propia hora local está estampada (obviamente). Y ambos dispositivos funcionando exactamente al mismo tiempo al nano segundo no es posible. Si debe ejecutarlo entre diferentes dispositivos, asegúrese de que tiene ntp en ejecución (para mantenerlos sincronizados). Dicho esto, está comparando el rendimiento antes y después del bufferedio (realmente no le importan los retrasos de tiempo reales, ¿verdad?), Por lo que la deriva del tiempo realmente no debería importar. Comparar un conjunto de resultados antes y después del almacenamiento intermedio es su interés real.

¡¡¡Disfruta !!!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top