0

The code I have posted below works for single file transfer over a socket. But it doesn't work for multiple file transfers over a socket. When trying multiple file transfers over the socket the code crashes.

I send multiple files by looping over the server sending code x amount of times, and run the receiving code x amount of times. When trying to send multiple files, the first file will send successfully, the second file name and size will be read successfully but the error in my code happens after this.

In my receiving client I tried to use to suggestion posted here: Java multiple file transfer over socket but had no success.

The error is on the client side.

The question I am asking is: Why isn't this code working for multiple files, and how can I fix it?

Server Sending

try{
    byte[] bytes = new byte[(int)file.length()];
    FileInputStream fis = new FileInputStream(file);
    OutputStream os = socket.getOutputStream();

    out.println(file.getName()); // Send Filename
    out.println(file.length()); // Send filesize

    int count;
    while ((count = fis.read(bytes)) > 0) {
      os.write(bytes, 0, count);
    }
    os.flush();
    fis.close();
  }catch(IOException e){
    e.printStackTrace();
  }
}

Client Recieving

try{
  String file = in.readLine(); // Read filename
  int fileSize = Integer.parseInt(in.readLine()); // Read Filesize 
  //ERROR HAPPENING ON LINE ABOVE IN LOOPS AFTER THE FIRST
  byte [] buf  = new byte [fileSize];
  FileOutputStream fos = new FileOutputStream(file);
  InputStream is = socket.getInputStream();

  int count = 0;
  while (fileSize > 0 && (count = is.read(buf, 0, (int)Math.min(buf.length, fileSize))) != -1){
    fos.write(buf, 0, count);
    fileSize -= count;
  }

  fos.close();
}catch(IOException e){
  e.printStackTrace();
}

The error is a NumberFormatException, on loops after the first when the client is receiving part of a file for the input to the fileSize.

Community
  • 1
  • 1
tester
  • 415
  • 1
  • 5
  • 17

1 Answers1

1

Make sure you flush the PrintWriter before you then write raw bytes directly to the OutputStream that the PrintWriter is attached to. Otherwise, you could write any buffer data out of order to the underlying socket.

But more importantly, make sure that if you use buffered reading on the receiving end that you read the file bytes using the same buffer that receives the file name and file size. You should also transfer the File using smaller fixed chunks, don't allocate a single byte[] array for the entire file size, that is a waste of memory for large files, and likely to fail.

Server:

try{
    byte[] bytes = new byte[1024];

    FileInputStream fis = new FileInputStream(file);
    OutputStream os = socket.getOutputStream();
    BufferedOutputStream bos = new BufferedOutputStream(os);

    PrinterWriter pw = new PrintWriter(bos);
    pw.println(file.getName()); // Send Filename
    pw.println(file.length()); // Send filesize
    pw.flush();

    int count;
    while ((count = fis.read(bytes)) > 0) {
      bos.write(bytes, 0, count);
    }
    bos.flush();
    fis.close();
  }catch(IOException e){
    e.printStackTrace();
  }
}

Client:

try{
  byte [] buf  = new byte [1024];

  FileOutputStream fos = new FileOutputStream(file);
  InputStream is = socket.getInputStream();
  BufferedInputStream bis = new BufferedInputStream(is);

  InputStreamReader isr = new InputStreamReader(bis);
  String file = isr.readLine(); // Read filename
  long fileSize = Long.parseLong(isr.readLine()); // Read Filesize 

  int count = 0;
  while ((fileSize > 0) && (count = bis.read(buf, 0, (int)Math.min(buf.length, fileSize))) > 0){
    fos.write(buf, 0, count);
    fileSize -= count;
  }

  fos.close();
}catch(IOException e){
  e.printStackTrace();
}

That being said, you might also consider using DataOutputStream.writeLong() and DataInputStream.readLong() to send/receive the file size in its original binary format instead of as a textual string:

Server:

try{
    byte[] bytes = new byte[1024];

    FileInputStream fis = new FileInputStream(file);
    OutputStream os = socket.getOutputStream();
    BufferedOutputStream bos = new BufferedOutputStream(os);

    PrinterWriter pw = new PrintWriter(bos);
    pw.println(file.getName()); // Send Filename
    pw.flush();

    DataOutputStream dos = new DataOutputStream(bos);
    dos.writeLong(file.length()); // Send filesize
    dos.flush();

    int count;
    while ((count = fis.read(bytes)) > 0) {
      bos.write(bytes, 0, count);
    }
    bos.flush();
    fis.close();
  }catch(IOException e){
    e.printStackTrace();
  }
}

Client:

try{
  byte [] buf  = new byte [1024];

  FileOutputStream fos = new FileOutputStream(file);
  InputStream is = socket.getInputStream();
  BufferedInputStream bis = new BufferedInputStream(is);

  InputStreamReader isr = new InputStreamReader(bis);
  String file = isr.readLine(); // Read filename

  DataInputStream dis = new DataInputStream(bos);
  long fileSize = dis.readLong(); // Read Filesize 

  int count = 0;
  while ((fileSize > 0) && (count = bis.read(buf, 0, (int)Math.min(buf.length, fileSize))) > 0){
    fos.write(buf, 0, count);
    fileSize -= count;
  }

  fos.close();
}catch(IOException e){
  e.printStackTrace();
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thanks, for answering my question, now working perfectly with help from your given examples. – tester Apr 18 '17 at 15:00