0

I am doing a sample client-server socket project where the server sends a file to the client and the client saves it in a destination folder. It works well BUT it only works ONCE. I have to restart the server and reconnect the client in order to send another file.

What am I doing wrong?

Server:

public void doConnect() {
        try {
            InetAddress addr = InetAddress.getByName(currentIPaddress);
            serverSocket = new ServerSocket(4445, 50, addr);

            isServerStarted = true;

            socket = serverSocket.accept();

            inputStream = new ObjectInputStream(socket.getInputStream());
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            String command = inputStream.readUTF();
            this.statusBox.setText("Received message from Client: " + command);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Method that I use to send the file from server

public void sendFile() {
        fileEvent = new FileEvent();
        String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf("/") + 1, sourceFilePath.length());
        String path = sourceFilePath.substring(0, sourceFilePath.lastIndexOf("/") + 1);
        fileEvent.setDestinationDirectory(destinationPath);
        fileEvent.setFilename(fileName);
        fileEvent.setSourceDirectory(sourceFilePath);
        File file = new File(sourceFilePath);
        if (file.isFile()) {
            try {
                DataInputStream diStream = new DataInputStream(new FileInputStream(file));
                long len = (int) file.length();
                byte[] fileBytes = new byte[(int) len];
                int read = 0;
                int numRead = 0;
                while (read < fileBytes.length && (numRead = diStream.read(fileBytes, read, fileBytes.length - read)) >= 0) {
                    read = read + numRead;
                }
                fileEvent.setFileSize(len);
                fileEvent.setFileData(fileBytes);
                fileEvent.setStatus("Success");
            } catch (Exception e) {
                e.printStackTrace();
                fileEvent.setStatus("Error");
            }
        } else {
            System.out.println("path specified is not pointing to a file");
            fileEvent.setStatus("Error");
        }
        //Now writing the FileEvent object to socket
        try {
            outputStream.writeUTF("newfile");
            outputStream.flush();

            outputStream.writeObject(fileEvent);

            String result = inputStream.readUTF();
            System.out.println("client says: " + result);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Client

public void connect() {
        int retryCount = 0;

        while (!isConnected) {
            if (retryCount < 5) {
                try {
                    socket = new Socket(currentIPAddress, currentPort);

                    outputStream = new ObjectOutputStream(socket.getOutputStream());
                    inputStream = new ObjectInputStream(socket.getInputStream());
                    isConnected = true;

                    //connection success
                    String command = inputStream.readUTF();

                    if (command.equals("newfile")) {
                        this.clientCmdStatus.setText("Received a file from Server");
                        outputStream.writeUTF("Thanks Server! Client Received the file");
                        outputStream.flush();
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                        new Thread(new DownloadingThread()).start();
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                    retryCount++;
                }
            } else {
                //Timed out. Make sure Server is running & Retry
                retryCount = 0;
                break;
            }
        }
    }

Code used for downloading file in client

public void downloadFile() {
        try {
            fileEvent = (FileEvent) inputStream.readObject();
            if (fileEvent.getStatus().equalsIgnoreCase("Error")) {
                System.out.println("Error occurred ..So exiting");
                System.exit(0);
            }

            String outputFile = destinationPath + fileEvent.getFilename();

            if (!new File(destinationPath).exists()) {
                new File(destinationPath).mkdirs();
            }

            dstFile = new File(outputFile);
            fileOutputStream = new FileOutputStream(dstFile);
            fileOutputStream.write(fileEvent.getFileData());
            fileOutputStream.flush();
            fileOutputStream.close();
            System.out.println("Output file : " + outputFile + " is successfully saved ");
            serverResponsesBox.setText("File received from server: " + fileEvent.getFilename());

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
Jay
  • 4,873
  • 7
  • 72
  • 137
  • 1
    "...it only works once...". What happens when you try twice? Where is the code that tries twice, and what errors do you observe? – President James K. Polk Jan 21 '17 at 13:12
  • The server successfully sends the file. So it says.. and the client shows no response. The 2nd file doesn't get saved and I get no errors @JamesKPolk – Jay Jan 21 '17 at 13:19

1 Answers1

0

In order to get the server accept another (and more) connections, you have to put it into a loop

while(someConditionIndicatingYourServerShouldRun) {
   Socker socket = serverSocket.accept();
   //respond to the client

}

I'd recommend using a thread pool and submit the processing to the thread pool, i.e. by using an ExecutorService. Further, you should close Resources such as stream when finished, the "try-with-resources" construct helps you with that. So your code might look like this

ServerSocket serverSocket =  ...;
ExecutorService threadPool = Executors.newFixedThreadPool(10);
AtomicBoolean running = new AtomicBoolean(true);
while(running.get()) {
  Socket socket = serverSocket.accept();
  threadPool.submit(() -> {
    try(ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
        OutputStream os = new ObjectOutputStream(socket.getOutputStream())) {
        String command = is.readUTF();
        if("shutdown".equals(command)) {
          running.set(false);
        } else {
          this.statusBox.setText("Received message from Client: " + command);    
        }   
    } catch (IOException e) {
      e.printStackTrace();
    }
  });
}
Gerald Mücke
  • 10,724
  • 2
  • 50
  • 67