javamultithreadingsocketsmultiprocessingconnectexception

Multiple sockets cause ConnectException: Connection refused: connect


I am programming java in Eclipse on Windows XP. I have a multiprocess simulation which uses ProcessBuilder to run a server and two clients. The server starts a thread to listen to two different sockets - one for each client. I can comment out the code for each client and have the other work perfectly fine. When I try to run them both, one client will always error with ConnectException: Connection refused: connect. Which client it is seems to be whichever is running slower, though it's hard to say. I can pause after starting the server but before the clients, and netstat verifies that both sockets are active. What could be causing this? I have some simplified code below.

Update: Based on comments, I have edited the code to multithread the server on a single socket, but I am still having the same problem. The code below reflects the changes. It appears that the socket is being opened and closed by one client before the other has a chance to open it. I can throw pause statements at the end of each client which allows the other to finish, but this is a fix, not a solution. So now the real question is, how do I keep the ServerSocket listening until I instruct it to close?

server

try{
    server = new ServerSocket(sockNum); 
} catch (IOException e) {
        System.out.printf("Could not listen on port %d\n",sockNum);
        System.exit(-1);
}
while(true){
    ClientWorker w;
    try{
        Socket connection = server.accept();
        w = new ClientWorker(connection);
        Thread t = new Thread(w);
        t.start();
    } catch (IOException e) {
        System.out.printf("Accept failed: %d\n",sockNum);
        System.exit(-1);
    }
}

class ClientWorker implements Runnable {
    private Socket client;

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

          public void run(){
            Object line;
            ObjectInputStream in = null;
            PrintWriter out = null;
            try{
              in = new ObjectInputStream(client.getInputStream());
              out = new PrintWriter(client.getOutputStream(), true);
            } catch (IOException e) {
              System.out.println("in or out failed");
              System.exit(-1);
            }

            while(true){
                try{
                    line = in.readObject();
                    //Send data back to client
                    out.println("Sent from broker");
                    if(line instanceof String)
                        System.out.println(line);
                    else
                        System.out.println(line.getClass());                        
                } catch (IOException e) {
                    System.out.println("Read failed");
                    System.exit(-1);
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

clients

 try{
    socket = new Socket("localhost", socketNum);
    out = new ObjectOutputStream(socket.getOutputStream());
    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

    out.writeObject(message);
    String line = in.readLine();
    System.out.println(line);
    } catch (UnknownHostException e) {
        System.out.println("Unknown host: localhost.eng");
        System.exit(1);
    } catch  (IOException e) {
        System.out.println("No I/O");
        System.exit(1);
    }

Controller

ProcessBuilder server = new ProcessBuilder("java.exe","-Xss64m","-cp","bin;jscheme.jar","ServerProcess");
server.redirectErrorStream(true);
Process runServer = server.start();

ProcessBuilder clientA = new ProcessBuilder("java.exe","-Xss64m","-cp","bin;jscheme.jar","ClientAProcess");
clientA.redirectErrorStream(true);
Process runClientA = clientA.start();

ProcessBuilder clientB = new ProcessBuilder("java.exe","-Xss64m","-cp","bin;jscheme.jar","ClientBProcess");
clientB.redirectErrorStream(true);
Process runClientB = clientB.start();

Solution

  • From OP

    So in the process of addresses what I thought to be an unrelated issue, I seem to have fixed the initial problem. There are two primary things that I added. First, I set up the clients to send an "end" command when complete, so that the socket would not block when trying to readObject(). Second, (and I think this is what fixed it), I defined a timeout value for the ServerSocket, rather than leaving it undefined (aka infinite). When I went back to clean up my code after getting things working, I tried removing the pauses in the client processes, and things still worked! My guess is that with no defined timeout, when a single socket closed before the other was opened, the ServerSocket closed as well. With a timeout defined, the ServerSocket will wait until timed out before closing. (This is just a guess though.)

    Here is the current working code. Feel free to comment if you think there's a different cause for the fix.

    server

    try{
        server = new ServerSocket(sockNum);
        server.setSoTimeout(timeOut);
    } catch (IOException e) {
        System.out.printf("Could not listen on port %d\n",sockNum);
        System.exit(-1);
    }
    
    while(isActive){
        ClientWorker w;
        try{
            Socket connection = server.accept();
            w = new ClientWorker(connection);
            Thread t = new Thread(w);
            t.start();
        } catch (IOException e) {
            if(e instanceof SocketTimeoutException)
                isActive = false;
            else{
                System.out.printf("Accept failed: %d\n",sockNum);
                System.exit(-1);
            }
        }
    }
    
     class ClientWorker implements Runnable {
            private Socket client;
            private Source source = Source.NONE;
            private String sourceName = "?";
            private Boolean threadActive = true;
    
            ClientWorker(Socket client) {
                this.client = client;
            }
    
            public void run(){
                Object line;
                ObjectInputStream in = null;
                PrintWriter out = null;
                try{
                    in = new ObjectInputStream(client.getInputStream());
                    out = new PrintWriter(client.getOutputStream(), true);
                } catch (IOException e) {
                    System.out.println("in or out failed");
                    System.exit(-1);
                }
    
                while(threadActive){
                    try{
                        line = in.readObject();
                        if(line instanceof String){
                            if(line.equals("end")){
                                threadActive = false;
                            }else
                                sourceName = line;
                            }
                        } else 
                            handleData;
                    } catch (IOException e) {
                        System.out.println("Read failed");
                        threadActive = false;
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        threadActive = false;
                    }
                }
                try {
                    this.client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }