6.7. Using Remote ObjectsEarlier in the chapter we mentioned some of the situations that might lead you to use message passing rather than remote objects to handle the agent-to-agent communication in your distributed system. To get a more concrete feeling for the differences between a message-passing system and one based on remote objects, this section describes an RMI implementation of our chess game. The RMI implementation of the chess game uses two remote objects: a remote chess player and a remote chess move. The interface for the RMIChessMove object is shown in Example 6-18. It has essentially the same interface as the ChessMove class in our earlier examples. Example 6-18. A Remote Chess Move Interface
Example 6-19 shows the RMIChessMoveImpl class, which is the server implementation of the chess move object. Example 6-19. Chess Move Implementation
Example 6-20 shows the interface for the RMIChessPlayer. It has essentially the same interface as the earlier ChessPlayer, except that we've changed the nextMove() method to return the player's move as an RMIChessMove object, rather than returning a boolean flag and filling in method arguments to indicate the move. We've also added a gameOver() method, which reveals whether the player has finished the game it was playing (win or lose). Example 6-20. Remote Chess Player Interface
The server implementation of the RMIChessPlayer is shown in Example 6-21 as the RMIChessPlayerImpl. Again, it's very similar to the ChessPlayer implementation, with the addition of the booleangameOver data member, the exceedingly simple gameOver() method, and a main() method. The main() method on the RMIChessPlayerImpl takes the place of the ChessServer in our message-passing chess game. If we call it with a single command line argument, then that argument is treated as the name used to register a local RMIChessPlayerImpl object with the RMI Naming service. Once the local player is registered with the RMI registry, the method loops waiting for a remote player to start a game, checking the local player to see when its game is over before quitting. If we invoke the class with a local player name plus a remote host name and remote player name on the command line, then the main() method tries to look up a remote RMIChessPlayer on that host under that name. If it finds one, it mediates a game between the remote and local players, iteratively calling each player's nextMove() and acceptMove() methods. Example 6-21. Chess Player Implementation
In this version of our chess game, the MessageHandler and the various Message subclasses have been replaced by the remote method-calling services provided by RMI. The RMI-based chess game is also easier to extend with new features--we just need to add new methods to our RMIChessPlayer interface. In the worst case, we'll need to define some new remote objects to support new features. In the message-passing version, we would need to extend the ChessPlayer interface, create new subclasses of Message to support the new functions, and update the ChessServer class to support the new message types. What we've lost in the RMI version is some flexibility in terms of the low-level communication protocol. Since RMI is encapsulating all of the network-level details of the remote method calls, we can't control the data protocol directly, as we do with message passing. If RMI's network protocol imposes too much overhead on our distributed system, there's little we can do about it except minimize the data members and method arguments on our remote objects. And if we're faced with a firewall that blocks the RMI protocol (perhaps for reasons that are known only to the network operator), then our distributed system is stopped dead in its tracks. With a simple (some would say barebones) message-passing system, we can directly control the format of both the serialized data and the communication protocol to suit our needs, and we can get our messages through using relatively "unadorned" IP packets. ![]() Copyright © 2001 O'Reilly & Associates. All rights reserved. |
|