Simon Leung
asked on
Multi client server Java program
I have written a client server programming. Currently, I find that it only allows two clients to go into the critical section (the synchronized code). If a third client is started, it can only go into the section if one the the client quit. I try to debug whole day but can't fix out what's wrong. Any idea or advise ?
Thx
Server
Cient
Thx
Server
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String args[]){
int PlayerIdx = 0;
Socket s=null;
ServerSocket ss2=null;
System.out.println("Server Listening......");
try{
ss2 = new ServerSocket(4445); // can also use static final PORT_NUM , when defined
}
catch(IOException e){
e.printStackTrace();
System.out.println("Server error");
}
GameWinner game = new GameWinner(false);
while(true){
try{
s= ss2.accept();
System.out.println("connection Established");
ServerThread st=new ServerThread(s, PlayerIdx, game); //start new thread for any incoming connection
PlayerIdx++;
st.start();
}
catch(Exception e){
e.printStackTrace();
System.out.println("Connection Error");
}
}
}
}
class GameWinner {
boolean gameover;
GameWinner(boolean bover)
{
this.gameover = bover;
}
boolean GetWinner(){
return gameover;
}
void SetWinner(boolean bover){
this.gameover = bover;
}
}
class ServerThread extends Thread{
String line=null;
BufferedReader is = null;
PrintWriter os=null;
Socket s=null;
int PlayerID;
boolean neverPlay= true;
GameWinner GamePlay;
public ServerThread(Socket s, int p, GameWinner g){
this.s=s;
this.PlayerID=p;
this.GamePlay=g;
}
public void run() {
try{
is= new BufferedReader(new InputStreamReader(s.getInputStream()));
os=new PrintWriter(s.getOutputStream());
}catch(IOException e){
System.out.println("IO error in server thread");
}
try {
line = "";
while (line.compareTo("QUIT")!=0) {
//Sync Start
synchronized(GamePlay) {
if ((neverPlay == false) ) {
try {
GamePlay.wait(); //wait for execution
}catch(InterruptedException e){
e.printStackTrace();
}
}
if (!GamePlay.GetWinner()) {
try{
os.println(PlayerID + ", your turn now" ); // send message to client
os.flush(); //forces any buffered output bytes to be written out to their intended destination
line=is.readLine();
System.out.println("Client Input : " + line);
System.out.println("Game Start");
Thread.currentThread().sleep(5000);
System.out.println("Game End");
}
catch (InterruptedException itro){
System.out.println("sleep is interrupted");
}
}
if (line.compareTo("OK")==0) {
line = "";
GamePlay.SetWinner(true);
System.out.println(PlayerID + " win the game.");
os.println("UWIN" ); // send message to client
os.flush(); //forces any buffered output bytes to be written out to their intended destination
}else if (GamePlay.GetWinner()) {
os.println("QUIT"); //send to the server
os.flush();
}
neverPlay=false;
GamePlay.notify(); //notify execution
} //Sync End
}
} catch (IOException e) {
line=this.getName(); //reused String line for getting thread name
System.out.println("IO Error/ Client "+line+" terminated abruptly");
}
catch(NullPointerException e){
line=this.getName(); //reused String line for getting thread name
System.out.println("Client "+line+" Closed");
}
finally{
try{
System.out.println("Connection Closing..");
if (is!=null){
is.close();
System.out.println(" Socket Input Stream Closed");
}
if(os!=null){
os.close();
System.out.println("Socket Out Closed");
}
if (s!=null){
s.close();
System.out.println("Socket Closed");
}
}
catch(IOException ie){
System.out.println("Socket Close Error");
}
}//end finally
}
}
Cient
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String args[]) throws IOException{
InetAddress address=InetAddress.getLocalHost();
Socket s1=null;
BufferedReader is=null;
String line=null;
BufferedReader br=null;
PrintWriter os=null;
try {
s1=new Socket(address, 4445);
//get server response, read from BufferedReader, console input
br= new BufferedReader(new InputStreamReader(System.in));
//get socket's input stream and open BufferedReader
is=new BufferedReader(new InputStreamReader(s1.getInputStream()));
//get sockets output stream and opens a PrinterWriter
//(send data through socket to server and write to PrinterWriter
os= new PrintWriter(s1.getOutputStream());
}
catch (IOException e){
e.printStackTrace();
System.err.print("IO Exception");
}
System.out.println("Client Address : "+address);
System.out.println("Enter Data to echo Server ( Enter QUIT to end):");
String response=null;
try{
line = "";
while(line.compareTo("QUIT")!=0){
response=is.readLine(); //read a line of information from BufferedReader connected to the socket
System.out.println("Server Response : "+response);
if (response.compareTo("UWIN")==0) {
System.out.println("You win the game ! " );
}
if ((response.compareTo("QUIT")!=0) && (response.compareTo("UWIN")!=0)){
line=br.readLine();
os.println(line); //send to the server
os.flush();
} else {
line = "QUIT";
os.println("QUIT"); //send to the server
os.flush();
break;
}
}
}
catch(IOException e){
e.printStackTrace();
System.out.println("Socket read Error");
}
finally{
br.close();os.close();br.close();s1.close();
System.out.println("Connection Closed");
}
}
}
I find that it only allows two clients to go into the critical section (the synchronized code).
Please point me to the synchronized section of your code, I can't spot it.
ASKER
Server :Line 100: synchronized(GamePlay) {
OK, I'll take a look. But a good idea to start along the more structured approach that ste5fan is outlining.
ASKER
The structured outlined by ste5fan is excellent but this is not the requirement that I want. Basically, multiclient can access the application at any time. Every client will take turn to access a synchronized code. If any one win the game will announcement the result and stop the whole application. Hence, I need to implement a synchronized code to ensure only one thread can execute at any time, but each thread get equal chance to access the code.
Thx
Thx
Well then the principle to follow then is the same as the one I’ve provided in your other question - Mary and co. all have an equal chance at the pool.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
The communication needs to reflect that. Thus you need communication for connecting, requesting to participate at a new game, and the actual game communication.
This means that you need to communicate between your threads. First with the "tournament managment" who coordinates when new games are started and when players are assigned to games, basically a kind of scheduler And then the "game director" which handles the actual game and the associated communication.
E.g. something like
Open in new window
The game and tournament class should be derived from a base class, which implements the state machine which does the command text parsing.