0

I'm sending some files over multiple TCP sockets (multiple, random ports), but every file sent ends up being corrupted. We first tested this as a standalone program with just one socket, which was working fine. But now implemented in our final project all our files get corrupted. I can't open any images, mp3 files, ...

Here is the file sender:

public class FileSenderThread implements Runnable {

    // Make a serverSocket
    protected ServerSocket serverSocket = null;
    protected Socket socket = null;
    protected String fileName = null;
    protected Long fileSize = null;
    protected String pathName = null;
    protected int port = 8500;

    public FileSenderThread(String name, Long size, int portNumber, String path) throws IOException {
        // get socket connection
        System.out.println("Init file transfer sender");
        this.port = portNumber;
        serverSocket = new ServerSocket(port);
        this.fileName = name;
        this.fileSize = size;
        this.pathName = path;
    }

    public void run() {
        try {
            socket = serverSocket.accept();
            System.out.println("Accepted connection : " + socket);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {

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

            // find the file & the size
            File transferFile = new File(pathName + fileName);
            System.out.println("size:" + fileSize);
            DataOutputStream outsize = new DataOutputStream(
                    socket.getOutputStream());
            outsize.writeLong(transferFile.length());

            // make bytearray from file
            byte[] bytearray = new byte[(int) transferFile.length()];

            FileInputStream fin = new FileInputStream(transferFile);
            BufferedInputStream bin = new BufferedInputStream(fin);
            bin.read(bytearray, 0, bytearray.length);

            System.out.println(bytearray.length);


            // open OutputStream and write bytearray
            OutputStream os = socket.getOutputStream();
            os.write(bytearray, 0, bytearray.length);
            os.flush();
            fin.close();
            bin.close();
            socket.close();
            System.out.println(fileName + " transfer complete");
        } catch (IOException ex) {
            System.out.println(ex);
        }

    }

}

end here is the file receiver:

public class FileReceiverThread implements Runnable {

    // Make a socket
    protected Socket socket = null;
    protected String fileName = null;
    protected Long fileSize = null;
    protected int port = 8500;

    public FileReceiverThread(String clientIp, String name, Long size, int randomPort)
            throws IOException {
        // get socket connection
        this.port = randomPort;
        System.out.println(clientIp);
        Socket socket = new Socket(clientIp, port);
        System.out.println("Connected to: " + socket);
        this.socket = socket;
        this.fileName = name;
        this.fileSize = size;
    }

    public void run() {
        int bytesRead;
        int currentTot = 0;
        int size = fileSize.intValue();

        // Create a buffer to hold temporary data
        byte[] byteArray = new byte[size];

        // Collect data
        InputStream iStream;
        try {
            iStream = socket.getInputStream();
            // Open a new file to write to
            FileOutputStream foStream = new FileOutputStream("files/replicated/" + fileName);
            // Write data to file via byteArray
            BufferedOutputStream boStream = new BufferedOutputStream(foStream);
            // Open inputStream to read from server
            bytesRead = iStream.read(byteArray, 0, byteArray.length);
            currentTot = bytesRead;

            do {
                // Read from inputStream into byteArray (buffer), start offset
                // in byteArray, maximum bytes to read from server in total
                // bytesRead is the number of bytes read in one loop from server
                bytesRead = iStream.read(byteArray, currentTot,
                        (byteArray.length - currentTot));

                // return value from bytesRead
                if (bytesRead >= 0) {
                    currentTot += bytesRead;
                }
                // if return value > 0, the file has been downloaded
            } while (bytesRead > -1);

            // Finish and write to file
            boStream.write(byteArray, 0, currentTot);
            System.out.println(fileName + " saved");
            // Close and empty outputBuffer
            boStream.flush();
            boStream.close();
            foStream.close();
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

What we actually do in the main class is:

  1. Find a randomport between 8500 & 65000
  2. open a new socket on the sender side & the receiver side on the same port
  3. send the file - receive the file
  4. close the file
  5. close the socket
boortmans
  • 1,138
  • 2
  • 24
  • 40
  • 1
    Maybe you have an problem with the charset? – Jens Dec 10 '14 at 08:06
  • What kind of files are you sending, and what does the corruption look like? (data left out, data inserted, data appended, data changed etc.) – Thomas Stets Dec 10 '14 at 08:11
  • You decorate your `Socket`'s `OutputStream` with a `DataOutputStream`. You then discard it and use the underlying `OutputStream`. `DataOutputStream` has a buffer, which you never flush. This is likely causing the corruption. I would recommend you avoid decorating and then discarding, and simply use the `DataOutputStream` to do all of your output. Further, there is no need to read the _entire file_ into memory! I also cannot see where you read the file size header at the other end... – Boris the Spider Dec 10 '14 at 08:12
  • If I send images, Windows says they are corrupted. If I send mp3's, I can't play them. So I guess there is data left out.. – boortmans Dec 10 '14 at 08:15
  • Create a small file with known content (maybe just one line of ASCII), transfer it, and check the difference (i.e. make a hex dump). As @Boris the Spider wrote, the most likely source of corruption is the file length you send before the file contents, which is no read on the client side and ends up within the file. – Thomas Stets Dec 10 '14 at 08:22
  • @ThomasStets I'm more worried about the unflushed stream. There seems to be a size argument to the accept method - must come from somewhere. As the stream is not flushed, the first 8 bytes will be ripped from the file and read as the size, this random amount will then be collected from the stream. – Boris the Spider Dec 10 '14 at 08:24
  • When I check the file in size, there are actually 8 bytes less then in the original file. – boortmans Dec 10 '14 at 08:29
  • Your receive code is nonsense. See the duplicated question. – user207421 Dec 10 '14 at 08:56

0 Answers0