0

I am trying to implement multi threading with a client/server program I have been working on. I need to allow multiple clients to connect to the server at the same time. I currently have 4 classes: a Client, a Server, a Protocol and a Worker to handle the threads. The following code is what I have for those classes:

SocketServer Class:

public class SocketServer {


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

        int portNumber = 9987;

        try ( 
            ServerSocket serverSocket = new ServerSocket(portNumber);
            Socket clientSocket = serverSocket.accept();
            PrintWriter out =
                new PrintWriter(clientSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));

        ) {
            Thread thread = new Thread(new ClientWorker(clientSocket));
            thread.start(); //start thread

            String inputLine, outputLine;

            // Initiate conversation with client
            Protocol prot = new Protocol();
            outputLine = prot.processInput(null);
            out.println(outputLine);

            while ((inputLine = in.readLine()) != null) {
                outputLine = prot.processInput(inputLine);
                out.println(outputLine);
                if (outputLine.equals("quit"))
                    break;
            }
        } catch (IOException e) {
            System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
            System.out.println(e.getMessage());
        }
    }
}

SocketClient Class:

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

        String hostName = "localhost";
        int portNumber = 9987;

        try (
            Socket socket = new Socket(hostName, portNumber);
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
        ) {
            BufferedReader stdIn =
            new BufferedReader(new InputStreamReader(System.in));
            String fromServer;
            String fromUser;

            while ((fromServer = in.readLine()) != null) {
                System.out.println("Server: " + fromServer);
                if (fromServer.equals("quit"))
                    break;

                fromUser = stdIn.readLine();
                if (fromUser != null) {
                    System.out.println("Client: " + fromUser);
                    out.println(fromUser);
                }
            }
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host " + hostName);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to " +
                hostName);
            System.exit(1);
        }
    }
}

Protocol Class:

public class Protocol {

    private static final int waiting         = 0;
    private static final int sentPrompt      = 1;


    private int status = waiting;

     public String processInput(String theInput) {
         String theOutput = null;

        if (status == waiting) {
            theOutput = "Please enter what you would like to retrieve: 'customer' or 'product' ";
            status = sentPrompt;
        }
        else if ( status == sentPrompt ) {
            if ( theInput.equalsIgnoreCase("product")) {
                File f = new File("product.txt");
                Scanner sc = null;
                try {
                    sc = new Scanner(f);
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(Protocol.class.getName()).log(Level.SEVERE, null, ex);
                }

                while ( sc.hasNextLine()  ) {
                    String line   = sc.nextLine();
                    theOutput = "The current product entries are : " + line;
                }
                return theOutput;
            }
            else if ( theInput.equalsIgnoreCase("customer")) {
                File f = new File("customer.txt");
                Scanner sc = null;
                try {
                    sc = new Scanner(f);
                } catch (FileNotFoundException ex) {
                    Logger.getLogger(Protocol.class.getName()).log(Level.SEVERE, null, ex);
                }

                while ( sc.hasNextLine()  ) {
                    String line   = sc.nextLine();
                    theOutput = "The current customer entries are : " + line;
                }
                return theOutput;

            }
            else if ( theInput.equalsIgnoreCase("quit")) {
                return "quit";
            }
            else {
                return "quit";
            }
        }
        return theOutput;
    }
}

The ClientWorker Class:

public class ClientWorker implements Runnable {
    private final Socket client;

    public ClientWorker( Socket client ) {
        this.client = client;
    }

    @Override
    public void run() {
        String line;
        BufferedReader in = null;
        PrintWriter out = null;
        try {
            System.out.println("Thread started with name:"+Thread.currentThread().getName());
            in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            out = new PrintWriter(client.getOutputStream(), true);
        } catch (IOException e) {
            System.out.println("in or out failed");
            System.exit(-1);
        }

        while (true) {
            try {
                System.out.println("Thread running with name:"+Thread.currentThread().getName());
                line = in.readLine();
                //Send data back to client
                out.println(line);
                //Append data to text area
            } catch (IOException e) {
                System.out.println("Read failed");
                System.exit(-1);
            }
        }
    }       
}

When I run the server and client, everything works fine as expected. Then when I try to run another client, it just hangs there and does not prompt the client to give a response. Any insight into what I am missing is greatly appreciated!

AgileDan
  • 361
  • 1
  • 2
  • 21
  • Where exactly does your program hang? I would guess in the while loop in the ServerSocket. – hotzst Oct 12 '15 at 18:36
  • @hotzst: Yes. I am open to using other ways, I have been looking into thread pools, too. But I need the Protocol to be used in every thread. – AgileDan Oct 12 '15 at 18:38
  • 2
    Side note on code quality: this code is almost horribly "not clean". I wholeheartedly recommend to start "Clean code" from Robert Martin for example to understand in how many ways you could improve your source code. – GhostCat Oct 12 '15 at 18:38
  • @Jägermeister: noted. Will do, thank you. – AgileDan Oct 12 '15 at 18:40

2 Answers2

3

Your server code should address implement below functionalities.

  1. Keep accepting socket from ServerSocket in a while loop

  2. Create new thread after accept() call by passing client socket i.e Socket

  3. Do IO processing in client socket thread e.g ClientWorker in your case.

Have a look at this article

Your code should be

ServerSocket serverSocket = new ServerSocket(portNumber);
while(true){
  try{
    Socket clientSocket = serverSocket.accept();
    Thread thread = new ClientWorker(clientSocket);
    thread.start(); //start thread
  }catch(Exception err){
     err.printStackTrace();
  }
}
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
2

How many times does serverSocket.accept() get called? Once. That's how many clients it will handle. Subsequent clients trying to contact will not have anybody listening to receive them.

To handle more clients, you need to call serverSocket.accept() in a loop.

janos
  • 120,954
  • 29
  • 226
  • 236