1

I am currently coding a simple TCP chat client-server application which works with sockets. A client connects to the server and as soon as it gets accepted, a new worker thread is created to listen for client input. Connecting to the sever (localhost at port 8818) works fine, but as soon as the worker thread starts listening for more client input after the login a java.net.SocketException: Connection reset is thrown (see stack trace below). I am aware that one possible source of this exception can be a socket that hasn't been closed properly or forcefully by either the server or the client. Therefore, my assumption is that I am not handling the closing of my client socket properly which causes the connection to reset.

What I would like to achieve: The worker listens for client input, as long as this is not null, requests (e.g. a simple login) are processed, otherwise, the socket is closed (see code excerpts below). My client receives a 'Login Successful' message from the server indicating that my handleLogin() function works, but instead of closing the socket after receiving no more input from the client, the server seems to just reset, even though clientSocket.close() is issued after the while loop.

Server.java

@Override
    public void run() {

        try {

            ServerSocket serverSocket = new ServerSocket(serverPort);

            while (true) {

                // Accept connection(s) from new chat client(s)
                System.out.println("SERVER: WAITING TO ACCEPT CLIENT CONNECTIONS ...");
                Socket clientSocket = serverSocket.accept();
                System.out.println("SERVER: CONNECTION ACCEPTED FROM: " + clientSocket);
                // Process client request in separate Thread
                WorkerThread worker = new WorkerThread(this, clientSocket);
                workerList.add(worker);
                worker.start();
            }

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

WorkerThread.java

 @Override
    public void run() {

        try {
            handleClientSocket();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }


    private void handleLogin(OutputStream outputStream, String[] tokens) throws IOException {

        if (tokens.length != 3) {
            outputStream.write("LOGIN FAILED!\n".getBytes());
                return;
        }

        // Extract username and password from user input
        String username = tokens[1];
        String password = tokens[2];

        if (username.equals("anna") && password.equals("anna")) {

            outputStream.write("Login successful!\n".getBytes());

        } else {
            outputStream.write("Error logging in!\n".getBytes());
        }

    }

    private void handleClientSocket() throws IOException, InterruptedException {

        InputStream inputStream = clientSocket.getInputStream();
        this.outputStream = clientSocket.getOutputStream();

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String line;

        // THIS IS WHERE THE EXCEPTION OCCURS AFTER CLIENT HAS LOGGED IN SUCCESSFULLY
        while ((line = bufferedReader.readLine()) != null) {

            String[] tokens = StringUtils.split(line);

            if (tokens.length > 0 && tokens != null) {

                String command = tokens[0];

                // Evaluate the entered command and handle the request accordingly

                if ("login".equalsIgnoreCase(command)) {
                    handleLogin(outputStream, tokens);
                } 

                // process other commands ...  

            }
        }

        clientSocket.close();   // POSSIBLY WORNG WAY OF CLOSING THE CLIENT SOCKET?
    }

Client.java

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

public class Client {

    private final String serverName;
    private final int serverPort;
    private Socket mySocket;
    private OutputStream serverOut;
    private InputStream serverIn;

    public Client(String serverName, int serverPort) {
        this.serverName = serverName;
        this.serverPort = serverPort;
    }

    private boolean connect() {

        try {
            mySocket = new Socket(serverName, serverPort);
            serverOut = mySocket.getOutputStream();
            serverIn = mySocket.getInputStream();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    private void login(String username, String password) throws IOException {
        String command = "login " + username + " " + password + "\n";
        serverOut.write(command.getBytes());
    }

    public static void main(String[] args) throws IOException {

        Client client = new Client("localhost", 8818);

        if (client.connect()) {                             
            System.out.println("Connection successful!");   
            client.login("anna", "anna");                   

        } else {
            System.err.println("Connection failed ...");
        }

    }

}

Stack Trace

java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:189)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at WorkerThread.handleClientSocket(WorkerThread.java:70)
    at WorkerThread.run(WorkerThread.java:45)

When I test my server with PUTTY (i.e. by connecting to localhost and then issuing commands in PUTTY's terminal), everything works just fine.

I am still fairly new to socket programming, so I also might have a logic flaw here. Any help will be much appreciated as I really would like to continue this project. Thanks in advance!

1
  • I think the connection is being closed by the client, I don't see any loop there waiting for more info after doing the login. Commented Mar 30, 2018 at 15:04

1 Answer 1

3

The reason of this exception is that you terminated the client once you connected the server, but the server still read something from the stream. The exception occurs. Here is the code I tested:

    while (inputStream.available() != 0) {
        line = bufferedReader.readLine();
        String[] tokens = StringUtils.split(line);

        if (tokens.length > 0 && tokens != null) {

            String command = tokens[0];

            // Evaluate the entered command and handle the request accordingly

            if ("login".equalsIgnoreCase(command)) {
                handleLogin(outputStream, tokens);
            } 

            // process other commands ...  

        }
    }

change the condition in while loop to check if the inputstream is still available to read.

Sign up to request clarification or add additional context in comments.

2 Comments

Works perfectly, thanks a bunch! :) Unfortunately I can not give you a proper upvote, but I accepted your answer!
That's fine. I am not for the upvote, so never mind that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.