0

In my client server application, it is able to receive commands and give the results back. The problem occures when I try to download a file from server side. After entering the download command, the server prompt shows this error,

java.net.SocketException: socket closed

Image:

Image

Otherwise the programing is working fine, also it is able to download the file into client side.

NB The possible reason I assuem is about the closing of outputSteram, (in my ServerSide project) that may not has been done in the right way.

My complete working code:

ServerSide:

    public class ServerSide {

    private BufferedReader inputFromClient;
    private PrintWriter outputToClient;
    private FileInputStream fis;
    private OutputStream os;
    private static final int PORT = 8000;
    private ServerSocket serverSocket;
    private Socket socket;

    public static void main(String[] args) {
        int port = PORT;
        if (args.length == 1) {
            port = Integer.parseInt(args[0]);
        }
        new ServerSide(port);
    }

    private boolean fileExists(File[] files, String filename) {
        boolean exists = false;
        for (File file : files) {
            if (filename.equals(file.getName())) {
                exists = true;
            }
        }
        return exists;
    }

    public ServerSide(int port) {
        // create a server socket
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException ex) {
            System.out.println("Error in server socket creation.");
            System.exit(1);
        }

        while (true) {
            try {

                socket = serverSocket.accept();
                 outputToClient = new PrintWriter(socket.getOutputStream());
                inputFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                while (true) {

                    String request = inputFromClient.readLine();

                    if (!request.startsWith("exit") && !request.startsWith("pwd") && !request.startsWith("list") && !request.startsWith("GET")) {
                        outputToClient.println("Wrong request\r\n"
                                + "\r\n");
                    } else if (request.startsWith("exit")) {
                        break;
                    } else if (request.startsWith("pwd")) {
                        File file = new File(System.getProperty("user.dir"));
                        outputToClient.print("Status OK\r\n"
                                + "Lines 1\r\n"
                                + "\r\n"
                                + "Working dir: " + file.getName() + "\r\n");
                    } else if (request.startsWith("list")) {
                        File file = new File(System.getProperty("user.dir"));
                        File[] files = file.listFiles();
                        outputToClient.print("Status OK\r\n"
                                + "Files " + files.length + "\r\n"
                                + "\r\n"
                                + Arrays.toString(files).substring(1, Arrays.toString(files).length() - 1) + "\r\n");
                    } else if (request.startsWith("GET")) {
                        String filename = request.substring(4);
                        File file = new File(System.getProperty("user.dir"));
                        File[] files = file.listFiles();

                        if (fileExists(files, filename)) {
                            file = new File(filename);
                            int fileSize = (int) file.length();

                            outputToClient.printf("Status OK\r\nSize %d Bytes\r\n\r\nFile %s Download was successfully\r\n",
                                    fileSize, filename);
                            outputToClient.flush();

                            try (FileInputStream fis = new FileInputStream(file)) {
                                os = socket.getOutputStream();
                                byte[] buffer = new byte[(1 << 7) - 1];
                                int bytesRead = 0;

                                while ((bytesRead = fis.read(buffer)) != -1) {
                                    os.write(buffer, 0, bytesRead);
                                }

                            }
                            os.close();//the problem probably occurs here.
                           // fis.close();
                        } else {
                            outputToClient.print("Status 400\r\n"
                                    + "File " + filename + " not found\r\n"
                                    + "\r\n");
                            outputToClient.flush();
                        }
                    }
                    outputToClient.flush();
                }
            } catch (IOException e) {
                System.err.println(e);
            }

        }
    }
}

ClientSide:

    public class ClientSide {

    private static Socket socket;
    private static PrintWriter outputToServer;
    private static BufferedReader inputFromServer;
    private static InputStream is;
    private static FileOutputStream fos;
    private static final int PORT = 8000;
    private static final String SERVER = "85.197.159.45";
    boolean Connected;
    DataInputStream serverInput;

    public static void main(String[] args) throws InterruptedException {
        String server = "localhost";
        int port = PORT;

        if (args.length >= 1) {
            server = args[0];
        }
        if (args.length >= 2) {
            port = Integer.parseInt(args[1]);
        }

        new ClientSide(server, port);
    }

    public ClientSide(String server, int port) {

        try {
            socket = new Socket(server, port);
            serverInput = new DataInputStream(socket.getInputStream());
            outputToServer = new PrintWriter(socket.getOutputStream(), true);
            inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println("Client is connected! ");
            Connected = true;
            String line = null;

            Scanner sc = new Scanner(System.in);
            System.out.print("Type command: ");

            while (sc.hasNextLine()) {
                String request = sc.nextLine();

                if (request.startsWith("exit")) {
                    outputToServer.println(request);
                    System.out.println("Application exited!");
                    //outputToServer.flush();
                    break;
                } else if (request.startsWith("pwd")) {
                    outputToServer.println(request);
                    outputToServer.flush();
                } else if (request.startsWith("list")) {
                    outputToServer.println(request);
                    outputToServer.flush();
                } else if (request.startsWith("GET")) {
                    System.out.print("\r\n");
                    outputToServer.println(request);
                    outputToServer.flush();
                }
                while (Connected) {
                    line = inputFromServer.readLine();
                    System.out.println(line);
                    if (line.isEmpty()) {
                        Connected = false;
                        if (inputFromServer.ready()) {
                            System.out.println(inputFromServer.readLine());
                        }
                    }
                    if (line.startsWith("Status 400")) {
                        while (!(line = inputFromServer.readLine()).isEmpty()) {
                            System.out.println(line);
                        }
                        break;
                    }
                    if (request.startsWith("GET")) {
                        File file = new File(request.substring(4));
                        is = socket.getInputStream();
                        fos = new FileOutputStream(file);

                        byte[] buffer = new byte[socket.getReceiveBufferSize()];
                        serverInput = new DataInputStream(socket.getInputStream());
                        //int bytesReceived = 0;
                        byte[] inputByte = new byte[4000];

                        int length;
                        while ((length = serverInput.read(inputByte, 0, inputByte.length)) > 0) {
                            fos.write(inputByte, 0, length);

                        }

                        /*
                         while ((bytesReceived = is.read(buffer)) >=0) {
                         //while ((bytesReceived = is.read(buffer))>=buffer) {
                         fos.write(buffer, 0, bytesReceived);
                         }
                         */
                        request = "";
                        fos.close();
                        is.close();
                    }
                }
                System.out.print("\nType command: ");
                Connected = true;
            }
            outputToServer.close();
            inputFromServer.close();
            socket.close();
        } catch (IOException e) {
            System.err.println(e);
        }

    }
}
Munira
  • 153
  • 16

3 Answers3

1

The problem, I think, is that in after processing that command (GET) you are closing the server socket in that os.close() call. Realize that both os outputToClient and inputFromClient depend on the same server socket. Thus, when closing os you are impacting the other two streams. Then, after serving the GET request you server loop goes to the beginning and tries to run inputFromClient.readLine() but the underlying socket has been closed.

Luis Rodero-Merino
  • 1,929
  • 1
  • 12
  • 8
  • Thanks. I have tried in different ways to solve it. Therefore I need to know how to implement that in coding. – Munira May 24 '15 at 19:04
  • I've seen that you also run is.close() in the client code when sending a GET. My suggestion: comment that line in the client and also os.close() in the server. – Luis Rodero-Merino May 24 '15 at 19:11
0

The Server is writing to the socket and after its done its closing the socket before the client had a chance to finish download/read it.You can instead make it so that once the client is done reading/download it sends a message to the server to close the socket.

Asura
  • 859
  • 5
  • 15
  • Asura, thanks, but I actually have researched so much about theoritical explanation about this issue. I applied those and it didnt work. Can you please specifically show that in my coding how to implement? – Munira May 24 '15 at 18:54
0

The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.

try(DataOutputStream out= new DataOutputStream(newFileOutputStream("data"))) 
{
       out.writeInt(666);
}

Alternatively you could make use of the finally block to close the stream after you've finished using it

try
{
  DataOutputStream out= new DataOutputStream(newFileOutputStream("data");
  out.writeInt(666);
}
catch(Exception e)
{
   e.printStackTrace();
}
finally
{
   if(out != null)
   { 
      out.close();
   }
}
Alan Kavanagh
  • 9,425
  • 7
  • 41
  • 65
  • Alan, thank you . But as u can see that I have two "try" block. Ater which try-catch block I need to add "finally" block. – Munira May 24 '15 at 18:50