Socket Communication between Java programs running on different JVMs

There are multiple ways to implement inter process communication. In this article, I will describe how to write a simple Ping Pong server. The objective will be, the first process sends a "PING" to the second process. The second process reads it and replies with a "PONG". Lets iterate this 10 times.

So, I will be using JDK 7 and will be using java.net.Socket class.

Socket is built for Client - Server communication. That means, a Server should be running on a port in order to accept messages. The clients can then send requests on the port.

So, the entire interaction revolves around both the java processes having both "Client" and "Server" threads running.
That means, when Process A wants to send a "PING" message to the Process B, Process A will use its client thread to send messages. The server thread in Process 2 should already be started and accepting messages, and similarly, when Process 2 wants to send a "PONG" message, it will use its client thread to send messages. The Process 1 should already be running its server thread to accept messages.

Lets go to the code structure.

We will have 4 files

  - PlayerA.java
  - PlayerB.java
  - ClientThread.java
  - ServerThread.java


PlayerA.java
public static void main(String[] args) {

The queue is needed to exchange information between Client and Server Thread running for the same process.

LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(1);
   queue.add("PING");
   
stopSignal will be used to stop Client and server thread. So, when a player has received 10 Messages, the client thread will set this object and the object will represent true. And the Server thread will keep checking the value of stopSignal object, and when it represents true, the server thread will also try to stop
The Server thread will communicate status to the client thread through a blocking queue. When the Server receives a message, it will add the message to the blocking queue, and the client thread will check the status of the queue and accordingly perform actions.So, even after setting  stopSignal to true, if the server still does not stop, we need to set ServerSocker.setSoTimeout to some milliseconds, after which the server will timeout and stop.

AtomicBoolean stopSignal = new AtomicBoolean(false);
   
Player 1, will act as a server on Port 25000, and connect to port 25001 as a client. Player 2 runs a server at port 25001, and will connect to 25000 as a client.

ClientThread clientThread = new ClientThread("localhost", 25001, queue, "Player1", stopSignal);
ServerThread serverThread = new ServerThread(25000, queue, "Player1", stopSignal);
new Thread(clientThread).start(); new Thread(serverThread).start();

PlayerB.java will also have similar code.

ClientThread.java

This class will run as a thread for both the players. Each player will have their own instance of ServerThread.
The instance will require port number, an instance of BlockingQueue, player name and StopSignal object. The BlockingQueue will be used for communication between client and server threads (Belonging to the same Player)

public class ClientThread implements Runnable {
private String host;
private int port;
private LinkedBlockingQueue<String> queue;
private String playerName;
private AtomicBoolean stopSignal;

ClientThread(String host, int port, LinkedBlockingQueue<String> queue, String playerName, AtomicBoolean stopSignal) {
                   this.host = host;
this.port = port;
this.queue = queue;
this.playerName = playerName;
this.stopSignal = stopSignal;
}

The thread will create a socket to connect to the port number.
It will simply receive a message, add a counter to it and and send it back. Each time it consumes a message, it will delete the message in BlockingQueue and The blocking queue will have a capacity of 1. 
public void run() {
int counter = 0;
while (true) {
  try {
            if(queue.size() == 1) {
               ++counter;

When already 10 messages have been sent, the if condition below checks that and will set the StopSignal object to true.

    if(11 == counter) {
       stopSignal.getAndSet(true);
       break;
    }
    InetAddress address = InetAddress.getByName(host);
    Socket socket = new Socket(address, port);
    OutputStream os = socket.getOutputStream();
    OutputStreamWriter osw = new OutputStreamWriter(os);
    BufferedWriter bw = new BufferedWriter(osw)

            String message;
    message = queue.take();
            if("PING".equals(message)){
              message = "PONG";
            }
            if("PONG".equals(message)){
              message = "PING";
            }

    bw.write(message);
    bw.flush();
    System.out.println(playerName + ":client sent Message" + message);
    queue.clear();
    }
         } catch (Exception exception) {
            System.out.println("Error Initialiazing Client Socket. Exception message:"+exception.getMessage());
            try {
Thread.sleep(2000);
    } catch (InterruptedException e) {
    }
    }

Check again if the message count has reached 10

if(counter == 10) {
   stopSignal.getAndSet(true);
   break;
}
}
}
}

Comments

Popular Posts