8 Clients and Servers P 2 Clients and

  • Slides: 35
Download presentation
8. Clients and Servers

8. Clients and Servers

P 2 — Clients and Servers Overview > RMI — Remote Method Invocation >

P 2 — Clients and Servers Overview > RMI — Remote Method Invocation > Remote interfaces > Serializable objects > Synchronization > Threads > Compiling and running an RMI application Sources > David Flanagan, Java Examples in a Nutshell, O’Reilly, 1997 > java. sun. com/products/jdk/rmi/ © O. Nierstrasz 2

P 2 — Clients and Servers A Networked Tic. Tac. Toe? We now have

P 2 — Clients and Servers A Networked Tic. Tac. Toe? We now have a usable GUI for our game, but it still supports only a single user. We would like to support: > players on separate machines > each running the game GUI locally > with a remote “game server” managing the state of the game © O. Nierstrasz 3

P 2 — Clients and Servers The concept © O. Nierstrasz 4

P 2 — Clients and Servers The concept © O. Nierstrasz 4

P 2 — Clients and Servers The problem Unfortunately Applets do not help to

P 2 — Clients and Servers The problem Unfortunately Applets do not help to implement this scenario! We must answer several questions: > Who creates the Game. Server? > How does the Game. Console connect to the Game. Server? > How do the server objects connect to the client objects? > How do we download objects (rather than just classes)? > How do the server objects synchronize concurrent requests? © O. Nierstrasz 5

P 2 — Clients and Servers Remote Method Invocation RMI allows an application to

P 2 — Clients and Servers Remote Method Invocation RMI allows an application to register a Java object under a public name with an RMI registry on the server machine. A client may look up up the service using the public name, and obtain a local object (stub) that acts as a proxy for the remote server object (represented by a skeleton). © O. Nierstrasz 6

P 2 — Clients and Servers Why do we need RMI? RMI > hides

P 2 — Clients and Servers Why do we need RMI? RMI > hides complexity of network protocols > offers a standard rmiregistry implementation > automates marshalling and unmarshalling of objects > automates generation of stubs and skeletons © O. Nierstrasz 7

P 2 — Clients and Servers Developing an RMI application There are several steps

P 2 — Clients and Servers Developing an RMI application There are several steps to using RMI: 1. Implement a server — Decide which objects will be remote servers and specify their interfaces — Implement the server objects 2. Implement a client — Clients must use the remote interfaces — Objects passed as parameters must be serializable 3. Compile and install the software 1. • Use the rmic compiler to generate stubs and skeletons for remote objects Run the application — Start the RMI registry 1. Start and register the servers 2. Start the client © O. Nierstrasz 8

P 2 — Clients and Servers Designing client/server interfaces Interfaces between clients and servers

P 2 — Clients and Servers Designing client/server interfaces Interfaces between clients and servers should be as small as possible. Low coupling: > simplifies development and debugging > maximizes independence > reduces communication overhead © O. Nierstrasz 9

P 2 — Clients and Servers Board. Game client/server interfaces We will split the

P 2 — Clients and Servers Board. Game client/server interfaces We will split the game into four packages: — — p 2. tictactoe — contains the server model p 2. tictactoe. gui — contains the client view p 2. tictactoe. rmi — contains the server interfaces p 2. tictactoe. server — contains the server implementation classes NB: The client’s Observer must be updated from the server side, so is also a “server”! © O. Nierstrasz 10

P 2 — Clients and Servers Identifying remote interfaces To implement the distributed game,

P 2 — Clients and Servers Identifying remote interfaces To implement the distributed game, we need three interfaces: Remote. Game. Server > called by the client to join a game > implemented by p 2. tictactoe. server. Game. Server Remote. Game > called by the client to query the game state and to handle moves > implemented by p 2. tictactoe. server. Game. Proxy — we simplify the game interface by hiding Player instances Remote. Observer > called by the server to propagate updates > implemented by p 2. tictactoe. server. Game. Observer © O. Nierstrasz 11

P 2 — Clients and Servers Specifying remote interfaces To define a remote interface:

P 2 — Clients and Servers Specifying remote interfaces To define a remote interface: > the interface must extend java. rmi. Remote > every method must be declared to throw java. rmi. Remote. Exception > every argument and return value must: — be a primitive data type (int, etc. ), or — be declared to implement java. io. Serializable, or — implement a Remote interface © O. Nierstrasz 12

P 2 — Clients and Servers Remote. Game. Server This interface is used by

P 2 — Clients and Servers Remote. Game. Server This interface is used by clients to join a game. If a game already exists, the client joins the existing game. Else a new game is made. public interface Remote. Game. Server extends Remote { public Remote. Game join. Tic. Tac. Toe() throws Remote. Exception; public Remote. Game join. Gomoku() throws Remote. Exception; } The object returned implements the Remote. Game interface. RMI will automatically create a stub on the client side and skeleton on the server side for the Remote. Game © O. Nierstrasz 13

P 2 — Clients and Servers Remote. Game exports only what is needed by

P 2 — Clients and Servers Remote. Game exports only what is needed by the client: public interface Remote. Game extends Remote { public boolean ready() throws Remote. Exception; public char join(). . . ; public boolean move(Move move). . . ; public int get_cols(). . . ; public int get_rows(). . . ; public char current. Player(). . . ; public String winner(). . . ; public boolean not. Over(). . . ; public void add. Observer(Remote. Observer o). . . ; public void restart(). . . ; public String name(). . . ; } Everything that is communicated must be either Remote or Serializable! © O. Nierstrasz 14

P 2 — Clients and Servers Remote. Observer This is the only interface the

P 2 — Clients and Servers Remote. Observer This is the only interface the client exports to the server: public interface Remote. Observer extends Remote { public void update(Move move) throws Remote. Exception; } NB: Remote. Observer is not compatible with java. util. Observer, since update() may throw a Remote. Exception. . . We will have to bridge the incompatibility on the server side. © O. Nierstrasz 15

P 2 — Clients and Servers Serializable objects Objects to be passed as values

P 2 — Clients and Servers Serializable objects Objects to be passed as values must be declared to implement java. io. Serializable. public class Move implements java. io. Serializable { public final int col; public final int row; public final char mark; public Move(int col, int row, char mark) {. . . } public String to. String() {. . . } } Move encapsulates the minimum information to communicate between client and server. © O. Nierstrasz 16

P 2 — Clients and Servers Implementing Remote objects should extend java. rmi. server.

P 2 — Clients and Servers Implementing Remote objects should extend java. rmi. server. Unicast. Remote. Object: public class Game. Server extends Unicast. Remote. Object implements Remote. Game. Factory { private Game. Factory tictactoe. Factory_, gomoku. Factory_; public static void main(String[] args) {. . . } public Game. Server () throws Remote. Exception { super(); tictactoe. Factory_ = new Tic. Tac. Toe. Factory(); gomoku. Factory_ = new Gomoku. Factory(); } . . . NB: All constructors for Remote objects must throw Remote. Exception! © O. Nierstrasz 17

P 2 — Clients and Servers Joining a game … public synchronized Remote. Game

P 2 — Clients and Servers Joining a game … public synchronized Remote. Game join. Tic. Tac. Toe() throws Remote. Exception { return new Game. Proxy(tictactoe. Factory_. get. Game()); } © O. Nierstrasz 18

P 2 — Clients and Servers Joining a game public abstract class Game. Factory

P 2 — Clients and Servers Joining a game public abstract class Game. Factory { protected Board. Game game_ = null; public Board. Game get. Game() { Board. Game game; if (game_ == null) { Player X = new GUIplayer('X'); Player O = new GUIplayer('O'); game_ = make. Game(X, O); // defer which game to create game = game_; } else { game = game_; game_ = null; } return game; } // Factory method by Tic. Tac. Toe. Factory and Gomoku. Factory protected abstract Board. Game make. Game(Player X, Player O); } © O. Nierstrasz 19

P 2 — Clients and Servers A simple view of synchronization A synchronized method

P 2 — Clients and Servers A simple view of synchronization A synchronized method obtains a lock for its object before executing its body. How can servers protect their state from concurrent requests? Declare their public methods as synchronized. © O. Nierstrasz 20

P 2 — Clients and Servers Registering a remote object The server must be

P 2 — Clients and Servers Registering a remote object The server must be started by an ordinary main() method: public static void main(String[] args) { if (System. get. Security. Manager() == null) { System. set. Security. Manager(new RMISecurity. Manager()); System. out. println("Set new Security manager"); }. . . There must be a security manager installed so that RMI can safely download classes! © O. Nierstrasz 21

P 2 — Clients and Servers Registering a remote object. . . The main()

P 2 — Clients and Servers Registering a remote object. . . The main() method must instantiate a Game. Server and register it with a running RMI registry. . if (args. length != 1) {. . . } String name = "//" + args[0] + "/Game. Factory"; try { Remote. Game. Server server = new Game. Server(); Naming. rebind(name, server ); } catch (Exception e) {. . . } } The argument is the host id and port number of the registry (e. g. , www. iam. unibe. ch: 7777) © O. Nierstrasz 22

P 2 — Clients and Servers Game. Proxy The Game. Proxy interprets Moves and

P 2 — Clients and Servers Game. Proxy The Game. Proxy interprets Moves and protects the client from any Invalid. Move. Exceptions: public class Game. Proxy extends Unicast. Remote. Object implements Remote. Game {. . . public synchronized boolean move(Move move) throws Remote. Exception { Player current = game_. current. Player(); if (current. mark() != move. mark) return false; try { game_. move(move. col, move. row, current); return true; // the move succeeded } catch (Invalid. Move. Exception e) { return false; } }. . . © O. Nierstrasz 23

P 2 — Clients and Servers Using Threads to protect the server We must

P 2 — Clients and Servers Using Threads to protect the server We must prevent the server from being blocked by a call to the remote client. Wrapped. Observer adapts a Remote. Observer to implement java. util. Observer: class Wrapped. Observer implements Observer { private Remote. Observer remote_; Wrapped. Observer(Remote. Observer ro) { remote_ = ro; }. . . © O. Nierstrasz 24

P 2 — Clients and Servers Using Threads to protect the server. . .

P 2 — Clients and Servers Using Threads to protect the server. . . public void update(Observable o, Object arg) { final Move move = (Move) arg; // for inner class Thread do. Update = new Thread() { public void run() { try { remote_. update(move); } catch(Remote. Exception err) { } } }; do. Update. start() ; // start the Thread } // and ignore results } Even if the Thread blocks, the server can continue. . . © O. Nierstrasz 25

P 2 — Clients and Servers Refactoring the Board. Game. . . Most of

P 2 — Clients and Servers Refactoring the Board. Game. . . Most of the changes were on the GUI side: > no changes to Drivers, Player, Runner > added name() to Tic. Tac. Toe and Gomoku > added Board. Game methods player() and add. Observer() — added Wrapped. Observer to adapt Remote. Observer > added remote interfaces and remote objects — made Move Serializable > changed all client classes — GUI classes now work with Remote. Game, not Board. Game — view now uses Move and Remote. Game (not Player) © O. Nierstrasz 26

P 2 — Clients and Servers Compiling the code We compile the source packages

P 2 — Clients and Servers Compiling the code We compile the source packages as usual, and install the results in a web-accessible location so that the server has access to the stub classes. © O. Nierstrasz 27

P 2 — Clients and Servers Generating Stubs and Skeletons In addition, the client

P 2 — Clients and Servers Generating Stubs and Skeletons In addition, the client and the server need access to the stub and skeleton class files. On Unix, chdir to the directory containing the client and tictactoe class file hierarchies rmic -d. tictactoe. Game. Factory rmic -d. tictactoe. Game. Proxy rmic -d. client. Game. Observer This will generate stub and skeleton class files for the remote objects. (I. e. , Game. Factory_Skel. class etc. ) — Update the ant build file accordingly NB: Move is not a remote object, so we do not need to run rmic on its class file. © O. Nierstrasz 28

P 2 — Clients and Servers Running the application 1. We start the RMI

P 2 — Clients and Servers Running the application 1. We start the RMI registry on the host 2. We start and register the servers rmiregistry ${port} & java -cp ${jar} -Djava. security. policy=policy. all -Djava. rmi. server. codebase="${codebase}" p 2. tictactoe. server. Game. Server ${host}: ${port} & 3. And start the clients … java -cp ${jar} -Djava. security. policy=policy. all p 2. tictactoe. gui. Game. Console ${host}: ${port} NB: the RMI registry needs the codebase so it can instantiate the stubs and skeletons! © O. Nierstrasz 29

P 2 — Clients and Servers Policy file You can control which permissions to

P 2 — Clients and Servers Policy file You can control which permissions to give to clients. This simple policy grants all permissions … grant { permission java. security. All. Permission; }; You may also need to shut off your firewall, or adopt one of several strategies to get RMI to work through the firewall … [See the RMI FAQ] © O. Nierstrasz 30

P 2 — Clients and Servers Playing the game © O. Nierstrasz 31

P 2 — Clients and Servers Playing the game © O. Nierstrasz 31

P 2 — Clients and Servers Other approaches CORBA > for non-java components COM

P 2 — Clients and Servers Other approaches CORBA > for non-java components COM (DCOM, Active-X. . . ) > for talking to MS applications Sockets > for talking other TCP/IP protocols Software buses > for sharing information across multiple applications © O. Nierstrasz 32

P 2 — Clients and Servers What you should know! How do you make

P 2 — Clients and Servers What you should know! How do you make a remote object available to clients? How does a client obtain access to a remote object? What are stubs and skeletons, and where do they come from? What requirements must a remote interface fulfil? What is the difference between a remote object and a serializable object? Why do servers often start new threads to handle requests? © O. Nierstrasz 33

P 2 — Clients and Servers Can you answer these questions? Suppose we modified

P 2 — Clients and Servers Can you answer these questions? Suppose we modified the view to work with Players instead of Moves. Should Players then be remote objects or serializable objects? Why don’t we have to declare the Abstract. Board. Game methods as synchronized? What kinds of tests would you write for the networked game? How would you extend the game to notify users when a second player is connected? What exactly happens when you send an object over the net via RMI? © O. Nierstrasz 34

P 2 — Clients and Servers License > http: //creativecommons. org/licenses/by-sa/2. 5/ Attribution-Share. Alike

P 2 — Clients and Servers License > http: //creativecommons. org/licenses/by-sa/2. 5/ Attribution-Share. Alike 2. 5 You are free: • to copy, distribute, display, and perform the work • to make derivative works • to make commercial use of the work Under the following conditions: Attribution. You must attribute the work in the manner specified by the author or licensor. Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one. • For any reuse or distribution, you must make clear to others the license terms of this work. • Any of these conditions can be waived if you get permission from the copyright holder. Your fair use and other rights are in no way affected by the above. © O. Nierstrasz 35