3
\$\begingroup\$

A multithreaded client server program to download image files. If you want to execute it on your machine you should change the file paths. Since there are four files to download the client makes the same number of connection attempts. The files sent by the FileServer will get repeated after the fourth connection attempt. In the File Server client app the file saving is done in new threads so as to not hamper the file downloading process. There is little interaction between client-server.

Here is the FileServer...

public class FileServer {
    private final ExecutorService exec = Executors.newCachedThreadPool();

    final String[] fileNames = {
            "C:\\Users\\clobo\\Pictures\\Ex1.jpg",
            "C:\\Users\\clobo\\Pictures\\Ex2.jpg",
            "C:\\Users\\clobo\\Pictures\\Ex3.jpg",
            "C:\\Users\\clobo\\Pictures\\Ex4.jpg"

    };

    public void start() throws IOException {
        ServerSocket socket = new ServerSocket(7777);
        System.out.println("Waiting for client message...");

        while (!exec.isShutdown()) {
            try {
                for (final String fileName : fileNames){
                     final Socket conn = socket.accept();

                    exec.execute(new Runnable() {
                        public void run() {
                            sendFile(conn,fileName);

                        }
                    });
                }
            } catch (RejectedExecutionException e) {
                if (!exec.isShutdown())
                    log("task submission rejected", e);
            }
        }
    }

    public void stop() {
        System.out.println("Shutting down server...");
        exec.shutdown();
    }

    private void log(String msg, Exception e) {
        Logger.getAnonymousLogger().log(Level.WARNING, msg, e);
    }

    public void sendFile(Socket conn, String fileName) {
        File myFile = new File(fileName);
        if (!myFile.exists()) {
            log("File does not exist!",null);
        }

        // file does exist
        System.out.println(Thread.currentThread().getName());
        System.out.println("AbsolutePath:" + myFile.getAbsolutePath());
        System.out.println("length: " + myFile.length());

        if (myFile.exists()) {
            try {
                ObjectOutputStream oos = new ObjectOutputStream(
                conn.getOutputStream());
                oos.writeObject(myFile);
                oos.close();
            } catch (IOException e) {
                log("IOException Error", e);
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {

        FileServer fs = new FileServer();
        fs.start();
    }
}

here is the FileServerClient...

public class FileServerClient {

    private final ExecutorService exec = Executors.newCachedThreadPool();
    Frame myFrame = new Frame();
    List<File> fileList = new ArrayList<File>();

    public void receiveFileFromServer() throws Exception{

        Socket sock = null;
        InputStream socketInputStream = null;
        String host = "localhost";
        int port = 7777;

        for (int i=0;i<4;i++) {

            sock = new Socket(host, port);
            socketInputStream = sock.getInputStream();
            System.out.println("Connection successful...");

            // recieve the file
            ObjectInputStream ois = new ObjectInputStream(socketInputStream);

            // file from server is deserialized
            final File myfile = (File) ois.readObject();
            fileList.add(myfile);

            // deserialized file properties 
            System.out.println("AbsolutePath: " + myfile.getAbsolutePath());
            System.out.println("FileName:" + myfile.getName());
            System.out.println("length" + myfile.length());
            exec.execute(new Runnable() {
                public void run() {

                    saveFile(myfile);

                }
            });

        }

    }

    private void saveFile(File myfile) {
        FileDialog fileDialog = new FileDialog(myFrame,
                "Choose Destination for "+ myfile.getName(), FileDialog.SAVE);
        fileDialog.setDirectory(null);
        fileDialog.setFile("enter file name here");
        fileDialog.setVisible(true);

        String targetFileName = fileDialog.getDirectory()
                + fileDialog.getFile() + ".jpg";

        System.out.println("File will be saved to: " + targetFileName);

        copyBytes(myfile, targetFileName);
    }

    private void copyBytes(File originalFile, String targetFileName) {

        try {
            FileInputStream in = new FileInputStream(originalFile);
            FileOutputStream out = new FileOutputStream(targetFileName);
            int c;

            while ((c = in.read()) != -1) {
                out.write(c);
            }
            out.close();
            in.close();

        } catch (Exception e) {
            log("IOException Error", e);
        }

    }

    private void log(String msg, Exception e) {
        Logger.getAnonymousLogger().log(Level.WARNING, msg, e);
    }

    public static void main(String[] args) throws Exception {

        FileServerClient client = new FileServerClient();

        client.receiveFileFromServer();

    }

}
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Is this code really doing what is advertised?

ObjectOutputStream.write(File) is writing the File object, not the contents of the file. So what we have here is the server pushing the path of a file to the client. The client code then creates a FileDialog, which doesn't wait for the user's input to get a second path on the client? Then a thread on the client runs to copy client(sourcePath) to client(destinationPath).

If you want the server to send the file to the client, then at some point the server needs to open the file, and write the contents into the connection.outputStream.

If two clients were trying to reach the server at the same time, they would each get a random list of file names, depending on the race condition in their own thread pools.

Server.stop, in addition to shutting down the Executor, should also signal start() to quit accepting connections.

Server.start() should probably be spelled "run()", given that it is an unending loop on the main thread. start() would be an acceptable spelling if socket.accept were running on a different thread (for instance, in your Executor).

\$\endgroup\$
0
\$\begingroup\$

Nice basic example. I guess your next step is to develop a server that gets a file download request, including a file-name parameter, and sends back the corresponding result.

See here http://www.binarytides.com/java-socket-programming-tutorial/ for an example about network data exchange. See here http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html for an example of a thread-pool based server that creates threads only when needed. The example is a bit out-dated, so they implement the ThreadPool class (came available in SDK only a few years ago), but of course you should keep using the version from the SDK.

\$\endgroup\$
3
  • \$\begingroup\$ When I run Server on one system and client on another system, then, on client it shows Exception \$\endgroup\$
    – devsda
    Commented Jan 17, 2013 at 4:35
  • \$\begingroup\$ and exception is on given link link \$\endgroup\$
    – devsda
    Commented Jan 17, 2013 at 5:18
  • \$\begingroup\$ Sounds like the path to the requested file is wrong. Cannot say much more, without the code. \$\endgroup\$
    – zakmck
    Commented Jan 17, 2013 at 12:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.