0

Consider the following Server:

public class TestServer {


public static void main(String[] args) {


    String ksName = "/some/path/keystore-server.jks";
    char ksPass[] = "password".toCharArray();
    char ctPass[] = "pswd".toCharArray();

    KeyStore ks;
    try {
        ks = KeyStore.getInstance("JKS");
        ks.load(new FileInputStream(ksName), ksPass);
        KeyManagerFactory kmf = 
        KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, ctPass);
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(kmf.getKeyManagers(), null, null);
        SSLServerSocketFactory ssf = sc.getServerSocketFactory();
        SSLServerSocket s   = (SSLServerSocket) ssf.createServerSocket(SERVER_PORT);                

        while(true){                
            SSLSocket sslsocket = (SSLSocket) s.accept();
            System.out.println("New Client accepted");
            TestThread t = new TestThread(sslsocket);
            t.run();      
        }

    } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException ex) {
        Logger.getLogger(TotalControlServer.class.getName()).log(Level.SEVERE, null, ex);
    }        
} 

}

The above is a simple server that accepts several clients: right after accepting a new connection, a dispatch a new thread (TestThread) in order to deal with the client incoming requests. Here's the code for TestThread:

public class TestThread implements Runnable {

SSLSocket sslsocket;

public TestThread(SSLSocket sslsocket) {
    this.sslsocket = sslsocket;
}

@Override
public void run() {

    ObjectInputStream is = null;
    ObjectOutputStream os = null;
    try {
        is = new ObjectInputStream(sslsocket.getInputStream());
        os = new ObjectOutputStream(sslsocket.getOutputStream());

        while(true){
            String p = (String) is.readObject();
            System.out.println("We got: " + p);

            os.writeObject(p.concat(p));
            os.flush();

        }//while         

    } catch (IOException ex) {
        Logger.getLogger(CmdLineService.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ClassNotFoundException ex) {
        Logger.getLogger(CmdLineService.class.getName()).log(Level.SEVERE, null, ex);
    } finally {
        try {
            is.close();
            os.close();
            this.sslsocket.close();
        } catch (IOException ex) {
            Logger.getLogger(CmdLineService.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}//run

}

Simple enough, it just loops indefinitely reading Strings and sending back its concatenation with itself.

The client is also rather simple:

public class TestClient {


  public static void main(String[] args) {

    System.setProperty("javax.net.ssl.trustStore" , "/path/keystore-client.jks")  ;
    ObjectOutputStream os = null;
    ObjectInputStream is = null;
    SSLSocket sslsocket = null;

    try {
        SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
        sslsocket = (SSLSocket) f.createSocket("localhost", SERVER_PORT);

        sslsocket.startHandshake();
        System.out.println("Authentication done");

        os = new ObjectOutputStream(sslsocket.getOutputStream());  
        is = new ObjectInputStream(sslsocket.getInputStream());


        BufferedReader b = new BufferedReader(new InputStreamReader(System.in)); 
        boolean exit = false;
        while(!exit){
            System.out.print("> ");
            String line = b.readLine();
            os.writeObject(line);
            os.flush();

            String s = (String) is.readObject();
            System.out.println(s);

        }//while

    } //main
    catch (IOException ex) {
        Logger.getLogger(TotalControlCmdClient.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ClassNotFoundException ex) {
          Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
      } finally {

        try {
            is.close();  
            sslsocket.close();
        } catch (IOException ex) {
            Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
        }
    }       
}

Just loops indefinitely sending strings and reading a string.

This works fine for one client.. However, if I start another client, it does not connect! It seems that I'm facing some kind of thread starvation issue..

How can I fix that?

nmpg
  • 561
  • 2
  • 10
  • 24

1 Answers1

1

The reason is simple: You never start a second listener Thread:

   while(true){                
            SSLSocket sslsocket = (SSLSocket) s.accept();
            System.out.println("New Client accepted");
            TestThread t = new TestThread(sslsocket);
            t.run();      
        } 

Calling run() does not start the Thread, that is done using start(). Therefore the main thread is processing the content of the run() method and as it is busy you can not connect using a second client.

Change t.run() to t.start and everything will be fine.

Robert
  • 39,162
  • 17
  • 99
  • 152
  • I'm surprised that the OP did not twig on to this when his/her debugger showed that execution never returned to the accept(). – Martin James Jun 26 '15 at 14:48
  • Yeah, after adding 'Thread T = new Thread(t); T.start()', it worked as expected. – nmpg Jun 27 '15 at 08:42