0

There are two parts to this task:

  1. Send a large file from client to the server in chunks. [DONE]
  2. The server receives the file, does some processing on the received file and then creates another results file. I need to send the results file back to the client from the server. [PROBLEM]

Problem: I am able to send file from client to server and do the processing to create the results file. But when I try to send the results file back to the client, the server keeps on listening to the client while receiving the initial input file and never moves to the processing step and hence the output file is never produced and never sent to the client.

Client side code

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

public class TCPClient {

    public static void main(String args[]) throws FileNotFoundException {
        // arguments supply message and hostname of destination
        String filePath = args[0];
        String server_address = args[1];

        Socket s = null;
        int count;
        int bufferSize=8192;
        String client_dir = "ClientFiles/";
        OutputStream os;

        File myFile= new File(filePath);
        byte[] buffer = new byte[bufferSize];
        FileInputStream fis = new FileInputStream(myFile);
        BufferedInputStream bis = new BufferedInputStream(fis);
        DataInputStream dis = new DataInputStream(bis);

        try {
            int serverPort = 7896;
            s = new Socket(server_address, serverPort);
            DataInputStream in = new DataInputStream(s.getInputStream());
            DataOutputStream out =
                    new DataOutputStream(s.getOutputStream());
            out.writeUTF(myFile.getName());

            while ((count = dis.read(buffer)) > 0) {
                out.write(buffer, 0, count);
            }
            System.out.println("Sent dataset to Server: " + filePath);

            // Receive results file from server
            String out_fileName = in.readUTF();
            File file = new File(client_dir);
            if (!file.isDirectory()){
                file.mkdirs();
                System.out.println(client_dir + " directory created for receiving results file");
            }
            String out_filePath = client_dir + out_fileName;
            OutputStream output = new FileOutputStream(out_filePath);
            byte[] in_buffer = new byte[bufferSize];
            int chunk = 1;
            while((count = in.read(in_buffer)) > 0){
                output.write(in_buffer, 0, count);
                System.out.println("Read chunk " + chunk + ": size = " + count + " bytes");
                chunk++;
            }
            float total_size = (float)(new File(out_filePath).length()) / 1024;
            System.out.println("Received \"" + out_fileName + "\" of total size " +
                    + total_size + " Kilobytes completely");
            System.out.println("Output file saved at \"" + out_filePath + "\"");

            try {
                File myObj = new File(out_filePath);
                Scanner myReader = new Scanner(myObj);
                while (myReader.hasNextLine()) {
                    String data = myReader.nextLine();
                    System.out.println(data);
                }
                myReader.close();
            } catch (FileNotFoundException e) {
                System.out.println("An error occurred.");
                e.printStackTrace();
            }

            System.out.println("Received: " + out_fileName);
        } catch (UnknownHostException e) {
            System.out.println("Sock:" + e.getMessage());
        } catch (EOFException e) {
            System.out.println("EOF:" + e.getMessage());
        } catch (IOException e) {
            System.out.println("IO:" + e.getMessage());
        } finally {
            if (s != null)
                try {
                    s.close();
                } catch (IOException e) {
                    System.out.println("close:" + e.getMessage());
                }
        }
    }
}

Server side code:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.Map;

public class TCPServer {
    public static void main(String args[]) {
        try {
            int serverPort = 7896;
            ServerSocket listenSocket = new ServerSocket(serverPort);
            System.out.println("TCP Server is running and accepting client connections...");
            while (true) {
                Socket clientSocket = listenSocket.accept();
                Connection c = new Connection(clientSocket);
            }
        } catch (IOException e) {
            System.out.println("Listen :" + e.getMessage());
        }
    }
}

class Connection extends Thread {
    DataInputStream in;
    DataOutputStream out;
    int bufferSize=8192;
    int count;
    Socket clientSocket;
    String server_dir = "ServerFiles/";

    public Connection(Socket aClientSocket) {
        try {
            clientSocket = aClientSocket;
            in = new DataInputStream(clientSocket.getInputStream());
            out = new DataOutputStream(clientSocket.getOutputStream());
            this.start();
        } catch (IOException e) {
            System.out.println("Connection:" + e.getMessage());
        }
    }

    public String get_results(String filePath) {
        System.out.println("Processing ...");
        
        // Does some processing on the input file to get a String output
        // processing code
        // ....

        results = "....."
        return results;
    }

    public void write_results(String results, String out_filePath){
        try {
            FileWriter myWriter = new FileWriter(out_filePath);
         
            myWriter.write(results);
            
            myWriter.close();
            System.out.println("Successfully wrote results to the file " + out_filePath);
        } catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }

    public void run() {
        try {   // an echo server
            String in_fileName = in.readUTF();
            System.out.println("Input Filename = \"" + in_fileName + "\"");
            File file = new File(server_dir);
            if (!file.isDirectory()){
                file.mkdirs();
                System.out.println(server_dir + " directory created for receiving file");
            }
            String in_filePath = server_dir + in_fileName;
            OutputStream output = new FileOutputStream(in_filePath);
            byte[] in_buffer = new byte[bufferSize];
            int chunk = 1;
            while((count = in.read(in_buffer)) > 0){
                output.write(in_buffer, 0, count);
                System.out.println("Read chunk " + chunk + ": size = " + count + " bytes");
                chunk++;
            }
            float total_size = (float)(new File(in_filePath).length()) / (1024 * 1024);
            System.out.println("Received \"" + in_fileName + "\" of total size " +
                     + total_size + " Megabytes completely");
            System.out.println("Input file saved at \"" + in_filePath + "\"");
            String results = get_results(in_filePath);

            String out_filePath = server_dir + "output_" +
                    in_fileName.substring(0, in_fileName.lastIndexOf('.')) + ".txt";
            write_results(results, out_filePath);

//             Send output file back to client
            File out_File= new File(out_filePath);
            out.writeUTF(out_File.getName());
            byte[] out_buffer = new byte[8192];
            FileInputStream fis = new FileInputStream(out_File);
            BufferedInputStream bis = new BufferedInputStream(fis);
            DataInputStream dis = new DataInputStream(bis);
            out.writeUTF(out_File.getName());
            while ((count = dis.read(out_buffer)) > 0) {
                out.write(out_buffer, 0, count);
            }
            System.out.println("Sent results file back to client: " + out_filePath);
        } catch (EOFException e) {
            System.out.println("EOF:" + e.getMessage());
        } catch (IOException e) {
            System.out.println("IO:" + e.getMessage());
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {/*close failed*/}
        }
    }
}

The server console is stuck at this:

...
Read chunk 36730: size = 8192 bytes
Read chunk 36731: size = 8192 bytes
Read chunk 36732: size = 4342 bytes
(running - waiting for more files)

The client console is stuck at this:

Sent dataset to Server: dataset/affr.csv
(Still running)

However, if I remove the portion of the server code to send the output file back from the server to the client and also remove the client code to receive the results file from the server, it works great and the output file is produced as well as shown below in server console:

Read chunk 36730: size = 8192 bytes
Read chunk 36731: size = 8192 bytes
Read chunk 36732: size = 4342 bytes
Received "affr.csv" of total size 286.9651 Megabytes completely
Input file saved at "ServerFiles/affr.csv"
Processing...
Successfully wrote results to the file ServerFiles/output_affr.txt
(running)

Client console:

Sent dataset to Server: dataset/affr.csv
(exited successfully)

I am new to Socket programming and JAVA. So, any inputs on this would be very helpful. Thanks in advance.

  • If you are trying to send data back and forth, doesnt the client have to act both as a client and as a server? Meaning 2 ports used? 1 for sending, and 1 for receiving? Same for the server, if it is meant to send messages back to the client, as well as to accept messages, then it needs to act as a server/client....2 socket ports. – JCompetence Feb 07 '21 at 20:23
  • Can't this be achieved by using a single port since the server sends the data back to the client only after reading the data completely from the client? Isn't input stream and outputstream in both client and server used for handling this? I have seen a simple workable example in which this is done but it sends and receives a simple String message instead of file and uses only `out.writeUTF(message)` and `data = in.readUTF(message)` – Ayush Kumar Shah Feb 07 '21 at 20:29
  • 1
    @SusanMustafa No, it doesn't mean that. It can all be done with a single connection. But he needs an application protocol. – user207421 Feb 08 '21 at 02:27
  • You need to send the length ahead of the file, so that the server knows when to stop reading it. You can adpat the code in my answer in the duplicate. – user207421 Feb 08 '21 at 02:27

0 Answers0