0

恢复文件传输时出现奇怪现象。

看看下面的图片,你会看到坏的部分。

这显然是随机发生的,可能每 10 次发生一次。
我通过 ftp 将图片从我的 Android 手机发送到 java 服务器。

我在这里忘记了什么。
我看到连接被终止,因为java.net.SocketTimeoutException:
传输正在像这样恢复

Resume at : 287609 Sending 976 bytes more

当文件完全接收时,字节总是正确的。即使是下面的图片。

不知道从哪里开始调试它,因为它大部分时间都在工作。

任何建议或想法都会很高兴,我想我在这里完全错过了一些东西。

在此处输入图像描述

设备发件人代码(仅发送循环):

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

    }
4

2 回答 2

2

发现错误,问题是我的错误逻辑。别说了。

我发送的图片在发送之前正在调整大小。

问题是在传输失败后恢复时
没有使用调整大小的图片,而是代码使用了
具有更大比例大小的原始图片。

我现在设置了一个短暂的缓存来保存调整大小的临时图片。

鉴于我制作的应用程序的复杂性,我只是忘记了恢复期间的文件与原始文件不同。

于 2012-01-23T22:59:44.013 回答
2

使用 BufferedOutputStream、BufferedInputStream,需要注意以下几点

  1. 在 BuffererdInputStream 之前创建 BufferedOutputStream(在客户端和服务器上)
  2. 并在创建后刷新。
  3. 每次写入后刷新(不仅仅是在关闭之前)

这对我有用。

已编辑

将 sentRequestTime、receivedRequestTime、sentResponseTime、receivedResponseTime 添加到您的数据包有效负载中。在这些上使用 System.nanoTime(),在同一主机上运行您的服务器和客户端,使用 ExecutorService 为该服务器运行多个客户端,并为请求和响应数据包绘制(接收-发送),在 Excel 图表上绘制时间延迟(一些 csv 格式)。在 bufferedIOStream 和 afterIOStream 之前执行此操作。您会很高兴知道您的绩效提高了 100%。让我很高兴绘制该图,花了大约 45 分钟。

我还听说使用自定义缓冲区可以进一步提高性能。

再次编辑在我的情况下,我使用的是 Object IOStreams,我向对象添加了 4 个长变量的有效负载,并在我从客户端发送数据包时初始化 sentRequestTime,在服务器接收到响应时初始化 receivedRequestTime,依此类推服务器对客户端的响应也是如此。然后我找到接收和发送时间之间的差异,以找出响应和请求的延迟。请小心在 localhost 上运行此测试。如果您在不同的硬件/设备之间运行它,它们的实际时间差可能会干扰您的测试结果。由于 requestReceivedTime 在服务器端带有时间戳,而 requestSentTime 在客户端带有时间戳。换句话说,他们自己的当地时间被标记(显然)。并且这两种设备的运行时间完全相同,达到纳秒是不可能的。如果您必须至少在不同设备之间运行它,请确保您运行了 ntp(以保持它们的时间同步)。也就是说,您正在比较 bufferedio 之前和之后的性能(您真的不关心实际的时间延迟吗?),所以时间漂移应该不重要。比较缓冲前和缓冲后的一组结果是您的实际兴趣。

享受!!!

于 2012-01-24T12:13:04.033 回答