0

As part of my Java course, I'm writing a server-client socket program that facilitates a file transfer. While the file transfer works fine, it always throws an exception whenever I try to close it from the client side.

The code for the server is as follows:

        String client = "";
        long size;
        //set the connection checker and disconnector
        boolean exit = false;

        try  {

            System.out.println("Client passed to thread");
            InputStream is = sock.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            DataInputStream dis = new DataInputStream(bis);


            while (!exit) {

                System.out.println("Client passed into while loop");
                //put the stuff in a while loop
                client = dis.readUTF();// can separate the types of input
                size = dis.readLong();

                if (client.equals("close".trim().toLowerCase())) {
                    System.out.println("Client disconnected");
                    dis.close();
                    bis.close();
                    is.close();
                    exit = true;
                    continue;
                } 
                
                else {

                    System.out.println("File received: " + client + "\nFile size: " + size);
                    // fileoutput is tacked onto output stream directly
                    OutputStream os = new FileOutputStream(client);
                    // create output stream to write to the file
                    BufferedOutputStream bos = new BufferedOutputStream(os);

                    byte[] buffer = new byte[4 * 1024];
                    int receivedBytes = 0;
                    long remainingBytes = 0;
                    System.out.println(receivedBytes + " received...");

                    while ((receivedBytes = dis.read(buffer)) > 0) {

                        bos.write(buffer, 0, receivedBytes);
                        remainingBytes = size - receivedBytes;
                        System.out.println(receivedBytes + " received...\n" + remainingBytes + "left");
                        bos.flush();
                        exit = true;

                    }

                    bos.close();
                    os.close();
                }
                
            }

            dis.close();
            bis.close();
            is.close();
           
            // if (size < 20.0) {
                
            //     System.out.println("File size insufficient, please include more stuff");
            // }

        } catch (IOException e) {
            e.printStackTrace();
            
        } finally {
            try {
                sock.close();
            } catch (IOException e) {
                
            }

        }

And the client code is here:

String input = "";
        long l = 1024;
        int fileData;

        Console cons = System.console();
        Socket socket = new Socket(host, Integer.parseInt(port));

        while (!("close").equals(input.trim().toLowerCase())) {

            input = cons.readLine("Please indicate the file to be sent: \n");


            OutputStream os = socket.getOutputStream();
            BufferedOutputStream bos = new BufferedOutputStream(os);
            DataOutputStream dos = new DataOutputStream(bos);

            if (input.equals("close".trim().toLowerCase())) {

                dos.writeUTF(input);
                dos.writeLong(l);
                dos.flush();
                System.out.println("Gotcha. Disconnecting");
                break;
            }

            File toBeSent = new File(input);

            if (!toBeSent.exists()) {

                input = cons.readLine("That file does not exist. Would you like to create it: \n");

                if (input.equals("yes")) {

                    toBeSent.createNewFile();
                    System.out.println("File created, add something inside before sending");
                    continue;
                }
            }

            else {

                try {
                    dos.writeUTF(input);
                    dos.writeLong(toBeSent.length());
                    dos.flush();

                    InputStream is = new FileInputStream(toBeSent);

                    BufferedInputStream bis = new BufferedInputStream(is);

                    byte[] buffer = new byte[4 * 1024];
                    int size = 0;

                    while ((size = bis.read(buffer)) > 0) {

                        dos.write(buffer, 0, size);
                        dos.flush();
                    }

                    bis.close();
                    is.close();

                    continue;

                } catch (EOFException e) {

                }
                dos.close();
                bos.close();
                os.close();

            }
        }

This thing is, the server-side code

if (client.equals("close".trim().toLowerCase())) {
    System.out.println("Client disconnected");
    dis.close();
    bis.close();
    is.close();
    exit = true;
    continue;
} 

works just fine, but only as the first input. As soon as the rest of the server code runs, it throws an exception whenever I try to input "close" from the client:

java.net.SocketException: Connection reset
        at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:313)
        at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:340)
        at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:789)
        at java.base/java.net.Socket$SocketInputStream.read(Socket.java:1025)
        at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:258)
        at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:313)
        at java.base/java.io.BufferedInputStream.implRead(BufferedInputStream.java:386)       
        at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:365)
        at java.base/java.io.DataInputStream.read(DataInputStream.java:102)
        at sg.edu.nus.iss.ClientHandler.run(ClientHandler.java:70)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:577)  
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1623)

The aforementioned Line 70 is the start of the while loop below:

while ((receivedBytes = dis.read(buffer)) > 0) {

                        bos.write(buffer, 0, receivedBytes);
                        remainingBytes = size - receivedBytes;
                        System.out.println(receivedBytes + " received...\n" + remainingBytes + "left");
                        bos.flush();
                        exit = true;

                    }

Any insight would be greatly appreciated. Thank you!

  • take a look at [this](https://stackoverflow.com/a/4300803/16034206), it seems likely that you closed the socket while there are still remainingBytes to be read. It might be better to have the condition while remainingBytes > 0 – experiment unit 1998X May 09 '23 at 09:37
  • 2
    have you debugged your code? Also, you may want to refactor it: this -> "close".trim().toLowerCase()) makes no sense at all. – Stultuske May 09 '23 at 09:38
  • 1
    No point in trimming and lowercasing a word that is already trimmed and in lowercase. – RealSkeptic May 09 '23 at 10:20
  • The loop `while ((receivedBytes = dis.read(buffer)) > 0)` will only be terminated when the client closes the connection. It will not terminate after the client is done sending a file. – Thomas Kläger May 09 '23 at 11:28

0 Answers0