First of all I am not too sure how to explain that without sounding confusing so I’ll try to make it simple. I have a server app that “pairs” two clients together, as part of a two player game. The way that happens is that when the first client connects to the server, the socket connection is accepted, a new ClientProtocol thread is created with that client but not started. When another client connects to the server, he is added to the previous thread and then the thread is started. The thread knows two inputstream and two outputstream, one for each client. However when I try to read from either client or server side nothing happens. This works fine for a single client in a single thread. Here is some code:
Server side (main thread)
public static Queue<ContestProtocol> contesters;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
contesters = new LinkedList<ContestProtocol>();
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}
while (true) {
Socket socket = serverSocket.accept();
ObjectInputStream ois;
ObjectOutputStream oos;
try {
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
synchronized (contesters) {
if (contesters.size() == 0) {
Contester contester1 = new contester(ois, oos);
contesters.add(new ContestProtocol(contester1));
} else {
Contester contester2 = new Contester(ois, oos);
contesters.poll().hook(contester2).start();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
server side (ContestProtocol)
private Contester contester1, contester2;
public ContestProtocol(Contester contester1) {
super("ContestProtocol");
}
public ContestProtocol hook(Contester contester2) {
this.contester2 = contester2;
return this;
}
public void run() {
try {
contester1.getOOS().writeInt(-1);
contester2.getOOS().writeInt(-2);
} catch (Exception e) {
e.printStackTrace();
}
}
server side (contester):
public Contester(ObjectInputStream ois, ObjectOutputStream oos) {
this.ois = ois;
this.oos = oos;
}
public ObjectInputStream getOIS() {
return ois;
}
public ObjectOutputStream getOOS() {
return oos;
}
client side:
try {
socket = new Socket(serverAddr, 4444);
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
int selectedChampion = ois.readInt();
} catch (Exception e) {
e.printStackTrace();
}
The ContestProtocol Thread finishes executing without problem but both clients hang on readInt(). I do not understand why.
This has to do mutex or semaphore issue in accessing the resources:
The streams you are using- which in this case are ouput and input streams – are tring to read and write to the same resource.
Because all these processes are happening on a continues one thread, their threads are interrupting one another, and creating wait processes on one another.
One solution is that, you register event liseners on the stream objecs, so that whenever one is finished the other one only will start.