I have this client and server programs.
The client get a command from user, and send it to the server, and the server return the result (output of the command) to the client.
I have 2 classes Command and CommandResult (represents the command and the result), and I'm passing them as json with ObjectInput(/Output)Stream.
This is the code:
Client
Socket socket = new Socket("localhost", 1111);
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while (true) {
//get command from user
Scanner scanner = new Scanner(System.in);
System.out.println("Enter command:");
String cmd = scanner.nextLine();
Command command = new Command(cmd);
//send the command as json
String jsonCommand = new Gson().toJson(command);
out.writeObject(jsonCommand);
out.flush();
//get and print the result
String jsonCommandResult = (String) in.readObject();
CommandResult commandResult = new Gson().fromJson(jsonCommandResult, CommandResult.class);
System.out.println(commandResult.getOutput());
}
Server
ServerSocket serverSocket = new ServerSocket(1111);
Socket socket = serverSocket.accept();
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
while (true) {
//read the command
String cmd = (String) in.readObject();
Command command = new Gson().fromJson(cmd, Command.class);
//run() method will run the command with java Process and return the result
CommandResult commandResult = command.run();
//sent the result back to the client as json
String jsonCommandResult = new Gson().toJson(commandResult);
out.writeObject(jsonCommandResult);
out.flush();
}
Now, this is working fine when I have one client.
But if I'm trying to run a second instance of the client program, while the first one is still in the loop, it hangs in the ObjectInputStream constructor. (third line)
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
As I understand from the documentation, the constructor block until the corresponding ObjectOutputStream has been created.
Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.
In my case the server has not accept the new client yet, and therefore the ObjectOutputStream has not been created.
Now, what I want is to throw exception if a new client trying to connect while other client is connected to the same port. But I can't figure it out how to check if the port is now in use before calling this constructor.
As @Kayaman proposed in the comments, I created a
Runnable
class handles the current client.Then in the server, I'm looping on
serverSocket.accept()
and allowing only one client at the time by starting a new thread for the first client, and check whether the current client is finished his communication or not.Here is the final Server class.
In the Client class, I check if the Server is ready or not.