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();
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();
}
}
}