Up Previous Next

Let's have the client ask the server to broadcast the information everywhere.

So first the client changes:

import java.awt.*; 
import javax.swing.*; 
import java.rmi.*; 
import java.rmi.server.*; 
import java.awt.event.*; 

public class Client extends JFrame implements ClientInterface, KeyListener { 

  public Client(int columns, int rows) {
    this.setTitle("iceblox: client frame"); 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     
    this.setSize(columns * cellWidth + cellWidth / 2, (1 + rows) * cellHeight + cellHeight / 2); 
    getContentPane().add(new Surface(columns, rows), "Center"); 
    addKeyListener(this); 
    this.setVisible(true); 
  }  

  public void keyReleased(KeyEvent e) { } 
  public void keyTyped(KeyEvent e) { }

  public void keyPressed(KeyEvent e) {
    int val = e.getKeyCode(); 
    try {
	if (val == 38) server.broadcast(id, "up"); 
	else if (val == 39) server.broadcast(id, "right");
	else if (val == 40) server.broadcast(id, "down"); 
      else if (val == 37) server.broadcast(id, "left"); 
    } catch (Exception exception) {
      System.out.println("Glitch: " + exception); 
    }  
  } 

  int cellWidth = 30, cellHeight = 30; 

  class Surface extends JPanel {
    int columns, rows; 
    Surface(int columns, int rows) { 
      this.columns = columns; 
      this.rows = rows; 
    }
    int fontSize = 10; // in pixels 
    Font digitsFont = new Font("Serif", Font.PLAIN, fontSize); 
    public void paintComponent(Graphics g) {
      super.paintComponent(g); 
      ((Graphics2D)g).setFont(digitsFont); 
      g.setColor(Color.black); 
      g.fillRect(0, 0, columns * cellWidth, rows * cellHeight); 
      g.setColor(Color.gray); 
      for (int i = 0; i <= rows; i++) 
        g.drawLine(0, i * cellHeight, columns * cellWidth, i * cellHeight); 
	for (int i = 0; i < columns; i++) { 
        g.drawLine(i * cellWidth, 0, i * cellWidth, rows * cellHeight); 
        g.drawRect(0, 0, cellWidth * columns, cellHeight * rows); 
        g.setColor(Color.gray);
      } 
      for (int j = 0; j < columns; j = j + 1) 
        for (int i = 0; i < rows; i++)
          g.drawString(i + ", " + j, j * cellWidth + 2, i * cellHeight + fontSize);	    
    }  
  }

  ServerInterface server; 

  public void registerWith(ServerInterface server) throws RemoteException {
    this.server = server; 
    this.id = server.register(this);     
    System.out.println("I have registered, I have id: " + this.id); 
  } 

  int id = -1; 

  public static void main(String[] args) {
    try {
        ServerInterface far = (ServerInterface)Naming.lookup("rmi://" + args[0] +  ":" + args[1] + "/Dirac"); 
        int cols = 10, rows = 10; 
        Client here = new Client(cols, rows); 
        UnicastRemoteObject.exportObject(here); 
        here.registerWith(far); 
    } catch (Exception e) {
        System.out.println("Error in client..." + e); 
        e.printStackTrace();
    }
  } 
}
The server needs to change next, in two places (brown, blue):

import java.rmi.*;
import java.rmi.server.*; 
import java.rmi.registry.*; 

public class Server extends UnicastRemoteObject implements ServerInterface {
  public Server() throws RemoteException {
    System.out.println("Server being initialized..."); 
  }
  ClientInterface[] clients = new ClientInterface[100];  
  public synchronized int register(ClientInterface client) throws RemoteException {
    size++;
    try {
      clients[size] = client;
    } catch (Exception e) { 
      System.out.println("Darn: " + e); 
    } 
    return size; 
  } 
  int size = -1; 
  public void broadcast(int id, String action) throws RemoteException {
    for (int i = 0; i <= size; i++) {
      clients[i].update(id, action); 
    } 
  } 
  public static void main(String[] args) {
    System.setSecurityManager(new RMISecurityManager()); 
    try {
      Server pam = new Server(); 
      Registry cat = LocateRegistry.createRegistry(Integer.parseInt(args[0])); 
      cat.bind("Dirac", pam);
      System.out.println("Server is ready..."); 
    } catch (Exception e) {
      System.out.println("Server error: " + e + "... "); 
    } 
  } 

}
The server interface needs to support one of these changes:

import java.rmi.*; 

public interface ServerInterface extends Remote {
  public int register(ClientInterface client) throws RemoteException;
  public void broadcast(int name, String action) throws RemoteException; 
} 
The content of broadcast calling update, the client changes again.

import java.awt.*; 
import javax.swing.*; 
import java.rmi.*; 
import java.rmi.server.*; 
import java.awt.event.*; 

public class Client extends JFrame implements ClientInterface, KeyListener { 

  public Client(int columns, int rows) {
    this.setTitle("iceblox: client frame"); 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     
    this.setSize(columns * cellWidth + cellWidth / 2, (1 + rows) * cellHeight + cellHeight / 2); 
    getContentPane().add(new Surface(columns, rows), "Center"); 
    addKeyListener(this); 
    this.setVisible(true); 
  }  

  public void keyReleased(KeyEvent e) { } 
  public void keyTyped(KeyEvent e) { }

  public void keyPressed(KeyEvent e) {
    int val = e.getKeyCode(); 
    try {
	if (val == 38) server.broadcast(id, "up"); 
	else if (val == 39) server.broadcast(id, "right"); 
	else if (val == 40) server.broadcast(id, "down"); 
      else if (val == 37) server.broadcast(id, "left"); 
    } catch (Exception exception) {
      System.out.println("Glitch: " + exception); 
    }  
  } 

  int cellWidth = 30, cellHeight = 30; 

  class Surface extends JPanel {
    int columns, rows; 
    Surface(int columns, int rows) { 
      this.columns = columns; 
      this.rows = rows; 
    }
    int fontSize = 10; // in pixels 
    Font digitsFont = new Font("Serif", Font.PLAIN, fontSize); 
    public void paintComponent(Graphics g) {
      super.paintComponent(g); 
      ((Graphics2D)g).setFont(digitsFont); 
      g.setColor(Color.black); 
      g.fillRect(0, 0, columns * cellWidth, rows * cellHeight); 
      g.setColor(Color.gray); 
      for (int i = 0; i <= rows; i++) 
        g.drawLine(0, i * cellHeight, columns * cellWidth, i * cellHeight); 
	for (int i = 0; i < columns; i++) { 
        g.drawLine(i * cellWidth, 0, i * cellWidth, rows * cellHeight); 
        g.drawRect(0, 0, cellWidth * columns, cellHeight * rows); 
        g.setColor(Color.gray);
      } 
      for (int j = 0; j < columns; j = j + 1) 
        for (int i = 0; i < rows; i++)
          g.drawString(i + ", " + j, j * cellWidth + 2, i * cellHeight + fontSize);	    
    }  
  }

  public void update(int player, String action) {
    System.out.println("Player " + this.id + " updated by player " + player + " with action: " + action); 
  }

  ServerInterface server; 

  public void registerWith(ServerInterface server) throws RemoteException {
    this.server = server; 
    this.id = server.register(this);     
    System.out.println("I have registered, I have id: " + this.id); 
  } 

  int id = -1; 

  public static void main(String[] args) {
    try {
        ServerInterface far = (ServerInterface)Naming.lookup("rmi://" + args[0] +  ":" + args[1] + "/Dirac"); 
        int cols = 10, rows = 10; 
        Client here = new Client(cols, rows); 
        UnicastRemoteObject.exportObject(here); 
        here.registerWith(far); 
    } catch (Exception e) {
        System.out.println("Error in client..." + e); 
        e.printStackTrace();
    }
  } 
}
The client interface also.

import java.rmi.*;

public interface ClientInterface extends Remote{
  public void update(int player, String action) throws RemoteException;  
} 
We can test then the chat (both ways). First the monolithic setup:

And here's how it runs as separate programs on the local host:

We have four windows stacked in this last snapshot, for one server and three clients.

This page needs to be split into several, one for each change/step taken (maybe, maybe not).

Now let's make the clients visible in the shared world.


Up Previous Next