Building a chat application with RMI: The basic idea is: Multiple customers chat through the Apllet, the customer's chat content is displayed in their respective Textarea, to do this, need to do: 1, customers first register, inform the server The server is listening to a topic; 2. After the customer registration, send a message to the server; 3, the server will send the message to all the client listening to this topic;
Chat.java: Client Remote Interface.
ChatImpl.java: Implement the applet of the chat remote interface.
ChatServer.java: Server remote interface.
ChatServerImpl.java: Implement the application of the chat server remote interface.
Message.java: A message object.
ServerTalker.java: Buffer the thread of the client and server communication.
Talker.java: Buffer server and customer communication thread.
Namedialog.java: Enter the dialog box for the customer name.
File package structure: (except NameDialog.java) in $ homen / java / usples / util, the rest is put $ HOME / JAVA / EXAMPLES / CHAT)
$ HOME / JAVA / EXAMPLES / CHAT
$ HOME / JAVA / EXAMPLES / UTIL
Building a chat application implementation process with RMI:
• Define remote interfaces.
· Realization of server class chat servers.
• The implementation of the server class client.
First, define a remote interface
1. Define the chat server remote interface: package examples.chat; import java.rmi. *;
Public Interface ChatServer Extends Remote {// Register Chatter with Server Public Void Register (CHAT C, STRING NAME) THROWS RemoteException
// unregister chatter with server public void unregister (String name) throws RemoteException;
// Post Messages to the Server for Broadcast Public Void PostMessage (Message M).
// List chatter names currently logged INTO Server public string [] listChatters () throws remoteException;} 2. Define client remote interface: package example.chat; import java.rmi. *;
Public interface chat extends Remote {public void chatExce (Message M) THROWS RemoteException;} II, server class chat server implementation: 1. Declaration Remote Interface 2, define the constructor of the remote object 3, implement the method of remote call, Create an instance of a remote object and register
Package examples.chat; import java.rmi. *; import java.rmi.server. *; import java.rmi.registry. *; import java.util. *;
public class ChatServerImpl extends UnicastRemoteObject implements ChatServer {private Vector chatters = new Vector (); public ChatServerImpl () throws RemoteException {System.out.println ( "Initializing Server.");} public static void main (String args []) {Registry REG;
// set security manager to allow stub loading over the network system.setsecuritymanager ()); try {chatserverimpl cs = new chatserverImpl ();
// Create Registry Running on Port 5050 Reg = LocateRegistry.createRegistry (5050); // CREATE REGISTRY
// Bind CS in Registry Reg.bind ("ChatServerImpl", CS); System.out.Println ("Server Ready.");} catch (alleadyboundexception e) {system.out.println ("Name is already bound:" E); system.exit (0);} catch (transoteexception e) {system.out.println ("General Server error:" E); system.exit (0);}}} SYNCHRONIZED PUBLIC VOID Register (Chat C , String name) {chatters.addelement (new talker (c, name));} synchronized public void unregister (string name) {talker C; for (int i = 0; i For (int i = 0; i For (int i = 0; i Public class talker extends thread {private vector message = new vector (); private chat c; boolean isactive = true; private string name; Public Talker (chat c, string n) {c = C; name = n; start ();} public boolean addMessage (message e) {if (! isactive) Return False; synchronized (messages) {Messages.Addelement (e) } Resume (); return true;} public void run () {while {try {if (messages.isempty ()) suspend (); synchronized (message) {c.chatnotify ((message) Messages.elementat (0)); Messages.RemoveElelementat (0);}} catch (RemoteException E) {// Connection Down; Kill thread system.out.println ("remote" name); isactive = false; // why is this necessary ? Stop ();} yield (); // let Other Threads Compete for Resources}} PUBLIC STRING GETCHATTERNAME () {Return Name;}} The following is the Message class, which must be serialized Package examples.chat; import java.io. *; Public Class Message Implements Serializable {Private String Sender; Private String Message public Message (String sender, String message) {this.sender = sender; this.message = message;} public String getSender () {return sender;} public String getMessage () {return message;}} three, server-based client This is the client class, and it is also a Server class package example.chat; import java.rmi. *; Import java.rmi.server. *; Import java.net. *; Import java.awt. *; Import java.util . *; import java.applet *;. import java.awt.event *;. // ActionListener interface import examples.util *;. // For NameDialog classpublic class ChatImpl extends Applet implements Chat, ActionListener {private TextArea ta; // the main text window private TextField tf; // message input area private ChatServer cs; // reference to Chat method server private String name; // User's name private NameDialog nd; // pop-up to request user name private ServerTalker st; / / Thread for handling message sending Public chatException {system.out.println ("Starting Up chatter.");} public void init () {// set up applet's layout manager this.setLayout (New borderLayout ()); // Create Panel for Buttons Panel P = new panel (); p.setLayout (new flowLayout ()); // set ITS Layout Manager // Add Buttons To Panel Button DC = New Button ("Disconnect"), // Disconnect from Server LT = New Button ("List"), // List Users CT = New Button ("ClearText"); // Clear TextField Dc.SetBackground; // for Dramatic Effect P.Add (LT); P.Add (CT); P.Add (DC); // Create Text Widgets & Drawing Window TA = New Textarea (4, 40); // Message Window TA.setedItTable (false); // Read-Only Window TF = New TextField (40); // Text Entry Field // Add widgets to applet add (ta, "center"); add (tf, "south"); add (p, "north"); // add button panel // register applet as listner for widget actions lt.addActionListener (this); ct.addActionListener (this); dc.addactionListener (this); tf.addactionListener (this); // Create Dialog box for user name nd = new namedialog (New frame ("Enter Name", "Enter Your Name ", false); registerChatter (); // register the applet with server} public void registerchat () {name = nd.getname (); // get name from namedialog nd.setVisible (false); // Get Rid of Namedialog nd = null; try {// exportur Remote Methods UnicastRemoteObject.exportObject (this); // Lookup The Server's Remote Object Cs = (ChatServer) Naming.lookup ("RMI: //lysander.cs.ucsb.edu: 5050 / chatserverImpl); // Register Applet with Server Cs.register (this, name); // Start a communication thread st = new serverTalker (cs, name);} catch (recoteexception e) {system.out.println ("COULDN't Locate Registry); System.exit (0);} catch (MalforMedurLexception) e) {system.out.println ("Bad Binding URL: E); System.exit (0);} catch (notboundexception e) {system.out.println (" Service Not Bound. "); System.exit (0);}}} public void actionperformed (ActionEvent E) {string s = tf.getText (). Trim (); if (! S.equals (")) // Message Entered? {If (! St.addMessage (New Message (Name, S))) // Failed? ta.append ("*** server error *** / n"); Tf.Settext ("");} else if ("" "" "). EQUALS (" Cleartext ")) TA.SETTEXT (" "); Else IF (E.GetActionCommand (). Equals (" disconnect ")) { St.addMessage (New Message ("***" Name, "Logged Off. Bye."); try {cs.unregister (name);} catch (remoteexception x) {system.out.println (name " 's unregister failed: " x); system.exit (0);} cs = null; system.exit (0);} else if (E.GetActionCommand (). Equals (" list ") getUserList (); } Public void getuserlist () {string users [] = null; try {users = cs.listchatters ();} catch (remoteException e) {system.out.println (e); users = new string [1]; users [ 0] = "*** error";} // add user names to textarea for (int i = 0; i IMPORT JAVA.RMI. *; Class serverTalker Extends thread {private vector message = new vector (); private chatrver cs; Public Server CS, String Name {this.cs = cs; // send a welcome message message message.addeelement (New Message, "CONNECTED" Name)); this.start ();} public boolean AddMessage (Message E) {if (cs == null) {system.out.println ("Server Reference Is Null."); Return False;} Resume (); // Resume Thread, if Suspended Messages.Addelement (e) Return True;} public void Run () {while {{i (messages.isempty ()) suspend (); cs.postMeementat (0)); Messages.RemoveElementatatatatatatatatatatatatat (0); Messages.RemoveEleMentat (0)); Messages.RemoveEleMentat (0) );} Catch (RemoteException E) {system.out.println ("Error: Server Down?" E); cs = null; this.stop ();} yield ();}}} final, NameDialog Tool class, Handling events, this is an excessive applet, interested friends can rewrite: package example.util; import java.aw. *; Public class namedialog extends Dialog {private textfield tf = new textfield (20); private string value; Public Namedialog (Frame P, String T, Boolean Modal) {Super (p, t, modal); setLayout (New flowLayout ()); this.add ("Enter Your Name:"); this.add TF); this.add (New Button); this.Pack (); this.show ();} public boolean handleevent (E) {if (e.target instanceof button) {if (tf. GetText (). Length ()> 1) Value = tf.getText (). Trim (); return true;} return false;} public string getname () {while (value == null) try {thread.sleep (1 }} Catch (interruptedException exception {system.err.println ("exception:" exception.toString ());} Return Value;}} four, compile and deploy: 1. Compile the source file with Javac, note that you must Compile: javac -d $ homen / class * .java 2, generate Skeletons and Stubs with RMIC, Skeletons and Stubs encapsulates the communications details of customers and servers: RMIC -D $ homen / class example.chat.chatimpl examples.chat.chatserverImpl 3, start the server and client: • Create an HTML file: Appletiewer chatApplet.html · ok! Enter your name, you can talk, congratulations!