2

I'm trying to send a file from client to the server, but only ~8kb of lager files(~100kb) transferred. And pngs for example are not completely viewable. I really don't know why it stops earlier.

Sending small testfiles(~1 kb) works great.

The server part:

                    ServerSocket fileSocket = new ServerSocket(p);
                    boolean rdy = false;
                    while (!rdy) {
                        Socket client = fileSocket.accept();
                        String fileName = "C:/" + args[2];
                        String cmd = fileName + "\n";

                        OutputStreamWriter sWriter = new OutputStreamWriter(client.getOutputStream());
                        sWriter.write(cmd, 0, cmd.length());
                        sWriter.flush();

                        InputStream inStream = client.getInputStream();

                        FileOutputStream fileStream = new FileOutputStream(fileName);

                        byte[] buffer = new byte[client.getReceiveBufferSize()];

                        int bytesRead = 0;

                        while ((bytesRead = inStream.read(buffer)) > 0) {
                            fileStream.write(buffer, 0, bytesRead);
                        }
                        fileStream.flush();

                        ta.append("File transfered");

                        inStream.close();
                        fileStream.close();
                        rdy = true;
                    }
                    fileSocket.close();
                    return;

The client part:

Socket client = new Socket(ip, port);
        OutputStream outStream = client.getOutputStream();

        FileInputStream fileStream = new FileInputStream(fileName);

        byte[] buffer = new byte[(int) fileStream.getChannel().size()];

        int bytesRead = 0;

        System.out.println("Sending file: " + fileName);

        while ((bytesRead = fileStream.read(buffer)) > 0) {
            outStream.write(buffer, 0, bytesRead);
        }

        outStream.close();
        fileStream.close();
        client.close();
        return;
Michal Kordas
  • 10,475
  • 7
  • 58
  • 103
Marvin
  • 55
  • 11
  • You're writng something to the client but never reading it. Try it without that write. You could be triggering a connection reset that you haven't told us about. Or you got some other exception please post it and the stack trace, in your question. – user207421 Mar 14 '15 at 11:35
  • Doesn't this line `outStream.write(buffer, 0, bytesRead);` on the client cause the data loss? Couldn't it be writing less then told? – alk Mar 14 '15 at 11:36
  • @alk No, it blocks until all the data has been transferred. See the Javadoc. – user207421 Mar 14 '15 at 11:39
  • I get an Socket Exception(`java.net.SocketException: Connection reset at java.net.SocketInputStream.read(Unknown Source)`) here: `while ((bytesRead = inStream.read(buffer)) > 0) { fileStream.write(buffer, 0, bytesRead); }` – Marvin Mar 14 '15 at 12:14
  • As predicted. So what happpened when you tried it without the write? – user207421 Mar 14 '15 at 22:39

2 Answers2

0

The problem with your code is that you're assuming that the server side receives all data instantly, but this is not the case. You should first tell the server how big the image file is and then send your data. On the server side you first read the size and then wait till all data is received from the client.

Client

    Socket client = new Socket(ip, port);
    DataOutputStream outStream = new DataOutputStream(client.getOutputStream());

    FileInputStream fileStream = new FileInputStream(fileName);

    byte[] buffer = new byte[filename.length()];

    int bytesRead = 0;

    System.out.println("Sending file: " + fileName);
    outStream.writeInt(filename.length()); //write image size

    while ((bytesRead = fileStream.read(buffer)) > 0) {
        outStream.write(buffer, 0, bytesRead);
    }

    outStream.close();
    fileStream.close();
    client.close();
    return;

Server

                ServerSocket fileSocket = new ServerSocket(p);
                boolean rdy = false;
                while (!rdy) {
                    Socket client = fileSocket.accept();
                    String fileName = "C:/" + args[2];
                    String cmd = fileName + "\n";

                    OutputStreamWriter sWriter = new OutputStreamWriter(client.getOutputStream());
                    sWriter.write(cmd, 0, cmd.length());
                    sWriter.flush();

                    DataInputStream inStream = new DataInputStream(client.getInputStream());

                    FileOutputStream fileStream = new FileOutputStream(fileName);

                    while(inStream.available()<4) {} //wait for the size of an int
                    int imagesize = inStream.readInt();

                    byte[] buffer = new byte[imagesize];

                    while(inStream.available()<imagesize) {} //wait for all the image data
                    inStream.readFully(buffer);
                    fileStream.write(buffer, 0, imagesize);
                    fileStream.flush();

                    ta.append("File transfered");

                    inStream.close();
                    fileStream.close();
                    rdy = true;
                }
                fileSocket.close();
                return;
ByteBit
  • 333
  • 1
  • 9
  • I get a SocketWriteExeption in this line in the clientcode: outStream.write(buffer, 0, bytesRead); – Marvin Mar 14 '15 at 11:06
  • He is not assuming the server got all the data instantly, and he doesn't need to send the length ahead of the data, as he is closing after sending it, and reading to end of stream at the other end. Your `available()` loops are both completely unnecessary wastes of time, space, and CPU, as all the following reads will block. You're also sending the length of the filename instead of the length of the file. Complete, untested nonsense. – user207421 Mar 14 '15 at 11:39
-1

I realy thank you for your help guys.

Now I found a interessting class doing exactly what I need. Hope I could this could be a help for other people with the same problems.

Code from: http://www.adp-gmbh.ch

import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;

public class ByteStream {
  private static byte[] toByteArray(int in_int) {
    byte a[] = new byte[4];
    for (int i=0; i < 4; i++) {

      int  b_int = (in_int >> (i*8) ) & 255;
      byte b = (byte) ( b_int );

      a[i] = b;
     }
    return a;
  }

  private static int toInt(byte[] byte_array_4) {
    int ret = 0;  
    for (int i=0; i<4; i++) {
      int b = (int) byte_array_4[i];
      if (i<3 && b<0) {
        b=256+b;
      }
      ret += b << (i*8);
    }
    return ret;
  }

  public static int toInt(InputStream in) throws java.io.IOException {
    byte[] byte_array_4 = new byte[4];

    byte_array_4[0] = (byte) in.read();
    byte_array_4[1] = (byte) in.read();
    byte_array_4[2] = (byte) in.read();
    byte_array_4[3] = (byte) in.read();

    return toInt(byte_array_4);
  }

  public static String toString(InputStream ins) throws java.io.IOException {
    int len = toInt(ins);
    return toString(ins, len);
  }

  private static String toString(InputStream ins, int len) throws java.io.IOException {
    String ret=new String();
    for (int i=0; i<len;i++) {
      ret+=(char) ins.read();
    }
    return ret;
  }

  public static void toStream(OutputStream os, int i) throws java.io.IOException {
    byte [] byte_array_4 = toByteArray(i);
    os.write(byte_array_4);
  }

  public static void toStream(OutputStream os, String s) throws java.io.IOException {
    int len_s = s.length();
    toStream(os, len_s);
    for (int i=0;i<len_s;i++) {
      os.write((byte) s.charAt(i));
    }
    os.flush();
  }

  private static byte[] toByteArray(InputStream ins, int an_int) throws 
    java.io.IOException,  
    Exception{

    byte[] ret = new byte[an_int];

    int offset  = 0;
    int numRead = 0;
    int outstanding = an_int;

    while (
       (offset < an_int)
         &&
      (  (numRead = ins.read(ret, offset, outstanding)) > 0 )
    ) {
      offset     += numRead;
      outstanding = an_int - offset;
    }
    if (offset < ret.length) {
      throw new Exception("Could not completely read from stream, numRead="+numRead+", ret.length="+ret.length); // ???
    }
    return ret;
  }

  private static void toFile(InputStream ins, FileOutputStream fos, int len, int buf_size) throws 
        java.io.FileNotFoundException, 
        java.io.IOException {

    byte[] buffer = new byte[buf_size];

    int       len_read=0;
    int total_len_read=0;

    while ( total_len_read + buf_size <= len) {
      len_read = ins.read(buffer);
      total_len_read += len_read;
      fos.write(buffer, 0, len_read);
    }

    if (total_len_read < len) {
      toFile(ins, fos, len-total_len_read, buf_size/2);
    }
  }

  private static void toFile(InputStream ins, File file, int len) throws 
        java.io.FileNotFoundException, 
        java.io.IOException {

    FileOutputStream fos=new FileOutputStream(file);

    toFile(ins, fos, len, 1024);
  }

  public static void toFile(InputStream ins, File file) throws 
        java.io.FileNotFoundException, 
        java.io.IOException {

    int len = toInt(ins);
    toFile(ins, file, len);
  }

  public static void toStream(OutputStream os, File file) 
      throws java.io.FileNotFoundException,
             java.io.IOException{

    toStream(os, (int) file.length());

    byte b[]=new byte[1024];
    InputStream is = new FileInputStream(file);
    int numRead=0;

    while ( ( numRead=is.read(b)) > 0) {
      os.write(b, 0, numRead);
    }
    os.flush();
  }
}
Marvin
  • 55
  • 11
  • All this just a reimplementation of `DataOutputStream` and `DataInputStream`. I don't see anything here that actually solves the problem. – user207421 Mar 14 '15 at 22:38