Search code examples
javaserverconnectionclientfile-transfer

Java Server-Client Connection reset


I have server and client applications running on my local machine. Client takes file, changes it and sends to server, then server responds if the file is correct. Client does it multiple times, sending one file at a time. I send two files from client and on the second file I get Connection reset

Server snippet:

private void initServer() throws IOException {
    while (true) {
        ServerSocket server = new ServerSocket(55555);
        Socket fromclient = server.accept();

        InputStream sin = fromclient.getInputStream();
        OutputStream sout = fromclient.getOutputStream();

        DataInputStream in = new DataInputStream(sin);
        DataOutputStream out = new DataOutputStream(sout);

        String line = in.readUTF();

        if (line.equals("new file")) {
            long fileSize = in.readLong();

            tempSavedFile = new File("/home/evgeniy/Files/Downloads/temp");

            tempSavedFile.createNewFile();
            try (FileOutputStream fos = new FileOutputStream(tempSavedFile)) {
                int t;
                for (int i = 0; i < fileSize; i++) {
                    t = sin.read();
                    fos.write(t);
                }
            }

            if (checkPadding(tempSavedFile)) {
                out.writeInt(PADDING_OK_RESPONSE);
            } else {
                out.writeInt(PADDING_ERROR_RESPONSE);
            }
            out.flush();
        }
        out.close();
        in.close();
        sout.close();
        sin.close();
        fromclient.close();
        server.close();
    }
}

Client class that calls new thread in for loop

for (byte i = 0; i < 2; i++) {
Callable callable = new FileSender(tempFile);
        FutureTask<Integer> ftask = new FutureTask<>(callable);
        Thread thread = new Thread(ftask);            
        thread.start();

        int response = 3244;
        try {
            response = ftask.get();
        } catch (InterruptedException | ExecutionException ex) {
            Logger.getLogger(FXMLController.class.getName()).log(Level.SEVERE, null, ex);
        }
        putMessage(String.valueOf(response));

Client Callable thread:

public Integer call() throws Exception {
    Socket socket = new Socket(address, serverPort);
    InputStream sin = socket.getInputStream();
    OutputStream sout = socket.getOutputStream();
    DataInputStream in = new DataInputStream(sin);
    DataOutputStream out = new DataOutputStream(sout);

    out.writeUTF("new file");
    out.flush();

    out.writeLong(file.length);
    out.flush();

    sout.write(file);
    sout.flush();

    System.out.println(socket.isConnected());
    int response = in.readInt();
    System.out.println("--------RESP="+response);

    out.close();
    in.close();
    sin.close();
    sout.close();
    socket.close();
    return response;
}

As you can see I send two files, and get this console output on client app:

true
--------RESP=200
true
ноя 20, 2018 5:16:36 PM com.evgeniy_mh.paddingoracle.FXMLController SendFileToServer
SEVERE: null
java.util.concurrent.ExecutionException: java.net.SocketException: Connection reset

Also, I don't understand why socket is ok, but

int response = in.readInt();

raising Connection reset exception.


Solution

  • Your code creates a new ServerSocket and later closes the created server socket for every single request that it processes. The code does not use the same ServerSocket instance to serve multiple requests.


    The connection reset failure appears to be because of this, as when the second request is creating a socket connection with the server, the existing ServerSocket is closed and recreated on the same port leading to the connection being reset. For a start try taking out the ServerSocket creation outside the while loop.

    private void initServer() {
        try (ServerSocket server = new ServerSocket(5555)) {
            while (true) {
                Socket fromclient = server.accept();
    
            ... // remaining code
    
                fromclient.close();
            }
        } catch (IOException ioe) {
            // handle failures
        }
    }
    

    The try-with-resources handles the .close() call on the AutoCloseable server socket.


    Also, note that the requests would be processed serially on a single thread in your code. Usually the Socket obtained for a connection from the ServerSocket#accept() (or the streams derived from it) is passed to a separate thread for processing unlike your code that processes the requests serially.