0

I'm trying to develop a simple Java file transfer application using TCP. My current server code is as follows:

package tcp.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class FTPServer {

    public static void main(String[] args) {
        new FTPServer().go();
    }

    void go() {
        try {
            ServerSocket server = new ServerSocket(2015);
            System.out.println("server is running ....!");
            while (true) {
                Socket socket = server.accept();
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String file = reader.readLine();
                System.out.println("file to be downloaded is : " + file);
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
                while (true) {
                    int octet = bis.read();
                    if (octet == -1) {
                        break;
                    }
                    bos.write(octet);
                }
                 bos.flush();
                //bos.close();

            }
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }

}

Using my current server code above, the downlloding does not work as expected. the above code sends part of the file to the client , not the entire file. Note that I used the flush method to flush the buffer. but when I replace the flush () method by the close () method, the file is fully sent to the client whithout any loss. Could anyone please explain this behavior!

UPDATE: Here is the code of my client:

package tcp.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 *
 * @author aaa
 */
public class FTPClient {

    public static void main(String[] args) {
        String file = "JasperReports-Ultimate-Guide-3.pdf";
        try {
            InetAddress address = InetAddress.getLocalHost();
            Socket socket = new Socket(address, 2015);
            System.out.println("connection successfully established ....!");
            PrintWriter pw = new PrintWriter(socket.getOutputStream());
            pw.println(file);
            pw.flush();
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy" + file));
            while (true) {
                int octet = bis.read();
                if (octet == -1) {
                    break;
                }
                bos.write(octet);
            }
            bos.flush();
            System.out.println("file download is complete ...!");

        } catch (UnknownHostException ex) {
            System.out.println(ex.getMessage());
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }
}

Another behavior without the use of Socket. take the following code that copy a file from a source to a destination:

    public class CopieFile {
     static void fastCopy(String source, String destination) {

    try {
        FileInputStream fis = new FileInputStream(source);
        BufferedInputStream bis = new BufferedInputStream(fis);
        FileOutputStream fos = new FileOutputStream(destination);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        while (true) {
            int octet = bis.read();
            if (octet == -1) {
                break;
            }
            bos.write(octet);
        }
        bos.flush();
    } catch (FileNotFoundException ex) {
        System.out.println(ex.getMessage());
    } catch (IOException ex) {
        System.out.println(ex.getMessage());
    }
}
public static void main(String[] args) throws IOException {
        String source = "...";
        String destination = "...";
        fastCopy(source, destination);
}// end main
}// end class

the above code to copy a file from one location to another without any loss. Note well that I did not close the stream.

Kachna
  • 2,921
  • 2
  • 20
  • 34
  • There must be bytes which are not sent and close send them all (which are in the buffer). Try to put the flush after the write so it will be flushed after each write operation. – KriszDev Apr 14 '15 at 15:23
  • Why two `while (true) ` loops? – Sybren Apr 14 '15 at 15:23
  • How are you reading the contents on the client? Just a guess, but could be that all data is sent either way, but by not closing the Stream on the server a loop is not exited gracefully on the client causing it to appear as though not all data is received. – copeg Apr 14 '15 at 16:12

1 Answers1

2

If you never close the stream the client wil never get end of stream so it will never exit the read loop.

In any case the stream and the socket are about to go out of scope, so if you don't close them you have a resource leak.

Jean-François Savard
  • 20,626
  • 7
  • 49
  • 76
user207421
  • 305,947
  • 44
  • 307
  • 483
  • [`Object.finalize`](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#finalize()) should prevent resource leaks... but of course it's better practise to close the stream. – Siguza Apr 14 '15 at 18:51
  • @Siguza There is no 'should' about it. It will only prevent the leak if it ever runs, which is not guaranteed. It must not be relied on. – user207421 Apr 14 '15 at 18:54
  • @EJP closing the stream will close the socket, therefore, closing socket is unnecessary. is it true? – Kachna Apr 15 '15 at 15:58
  • @EJP: you said: "If you never close the stream the client wil never get end of stream so it will never exit the read loop". but why ? How about flush(). – Kachna Apr 16 '15 at 21:27
  • @Kachna 1. Your client exits the read loop at end of stream. End of stream only occurs on a socket when the peer closes the connection. 2. As closing the stream closes the socket *of course* closing the socket is redundant. I don't know why you're even asking. – user207421 Feb 28 '16 at 18:28