简体   繁体   中英

Java socket file transfer - Files don't transfer completely

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;

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;

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();
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM