001    /*
002     * 
003     * $id: Client.java,v 1.4 1998/07/08 16:11:11 tparnell Exp $
004     *
005     * Developed for "Rethinking CS101", a project of Lynn Andrea Stein's AP Group.
006     * For more information, see <a href="http://www.ai.mit.edu/projects/cs101/">the
007     * CS101 homepage</a> or email <las@ai.mit.edu>.
008     *
009     * Copyright (C) 1996 Massachusetts Institute of Technology.
010     * Please do not redistribute without obtaining permission.
011     */
012    package cs101.net;
013    
014    import cs101.awt.ClientDialog;
015    import java.io.*;
016    import java.net.*;
017    import cs101.util.StringHandler;
018    
019    /**
020     * A reasonably vanilla network client.  Works with Server.java. 
021     * To customize, provide it with a StringHandler, either at creation time or
022     * later.<p>
023     *
024     * If server's hostName and port are not provided at creation time, the user
025     * is prompted for this information using ClientDialog.<p>
026     * 
027     * Copyright 1996 Massachusetts Institute of Technology
028     *
029     * @see      cs101.net.Server
030     * @see      cs101.util.StringHandler
031     * @see      #setStringHandler
032     *
033     * @author   Todd C. Parnell, tparnell@ai.mit.edu
034     * @author   Maciej Stachowiak, maciej@ai.mit.edu 
035     * @author   Lynn Andrea Stein, las@ai.mit.edu
036     * @version  $Id: Client.java,v 1.1.1.1 2002/06/05 21:56:32 root Exp $
037     *
038     */
039    
040    public class Client implements Runnable, StringHandler {
041      /** Animates this object */
042      protected Thread spirit;
043    
044      /** Handles input from net */
045      protected StringHandler stringHandler; 
046    
047      /** Net connection */
048      protected Socket sock;
049      /** Where to read data */
050      protected ObjectInputStream ois;
051      /** Where to write data */
052      protected ObjectOutputStream oos;
053    
054      /** Flag to indicate whether the Thread animating this should stop */
055      private boolean stopped;
056    
057      /**
058       * Creates an autonomous client.  Send Strings using send; receive Strings
059       * as this client's StringHandler (it calls your handleString method).
060       *
061       * @param sh   the StringHandler to handle data this client receives from the net.
062       * @param hostName  the name of the machine that the server is on
063       * @param port      the port number on which the server is listening
064       *
065       * @see #send
066       * @see cs101.util.StringHandler
067       */
068      public Client ( String hostName, int port, StringHandler sh ) {
069        this.stringHandler = sh;
070        this.connectTo( hostName, port );
071      }
072    
073      /**
074       * Creates an autonomous client.  Send Strings using send; receive Strings
075       * as this client's StringHandler (it calls your handleString method).
076       * <p>
077       * StringHandler may be set later. Otherwise, this object's default method
078       * is used.
079       *
080       * @param hostName  the name of the machine that the server is on
081       * @param port      the port number on which the server is listening
082       *
083       * @see #send
084       * @see #setStringHandler
085       */
086      public Client ( String hostName, int port ) {
087        this.stringHandler = this;
088        this.connectTo( hostName, port );
089      }
090    
091      /**
092       * Creates an autonomous client.  Send Strings using send; receive Strings
093       * as this client's StringHandler (it calls your handleString method).
094       * <p>
095       * User is prompted for server's hostName and port (using ClientDialog).
096       * 
097       * @param sh   the StringHandler to handle data this client receives from the net.
098       *
099       * @see cs101.util.StringHandler
100       */
101      public Client ( StringHandler sh ) {
102        this.stringHandler = sh;
103        ClientDialog qd = new ClientDialog();
104        qd.ask();
105        this.connectTo( qd.getHostName(), qd.getPort() );
106      }
107    
108      /**
109       * Creates an autonomous client.  Send Strings using send; receive Strings
110       * as this client's StringHandler (it calls your handleString method).
111       * <p>
112       * StringHandler may be set later. Otherwise, this object's default method
113       * is used.
114       * <p>
115       * User is prompted for server's hostName and port (using ClientDialog).
116       * 
117       * @see #send
118       * @see #setStringHandler
119       */
120      public Client() {
121        this.stringHandler = this;
122        ClientDialog qd = new ClientDialog();
123        qd.ask();
124        this.connectTo( qd.getHostName(), qd.getPort() );
125      }
126    
127      /**
128       * Opens a connection to a server presumed to be listening on hostName,
129       * port.  Sets up listener thread.  Called by constructor; should not be
130       * called otherwise.
131       *
132       * @param hostName  the name of the machine that the server is on
133       * @param port      the port number on which the server is listening
134       */
135      protected void connectTo( String hostName, int port ) {
136        System.out.println("Client:  trying to connect to " + hostName
137                           + " on port " + port );
138        try {
139          this.sock = new Socket( hostName, port );
140          // create Output before Input
141          this.oos = new ObjectOutputStream(this.sock.getOutputStream());
142          this.ois = new ObjectInputStream(this.sock.getInputStream());
143        } catch (IOException e) {
144          throw new RuntimeException("Client:  " +
145                                     "can't establish communication with " + 
146                                     hostName + " on port " + port );
147        }
148        this.spirit = new Thread( this );
149        this.spirit.start();
150      }
151    
152      /**
153       * Reads Strings from the server connection.  Called by this object's Thread.
154       * Should not be called otherwise.
155       */
156      public void run() {
157        System.out.println( "Client:  starting read loop." );
158        try {
159          while ( !this.stopped ) {
160            this.stringHandler.handleString( (String)this.ois.readObject() );
161          }
162        } catch (OptionalDataException ode) {
163          throw new RuntimeException("Client: readObject() failed with OptionalDataException.");
164        } catch (IOException e) {
165          throw new RuntimeException("Client:  failed to read");
166        } catch (ClassNotFoundException cnfe) {
167          throw new RuntimeException("Client: readObject() failed with ClassNotFoundException.");
168        }
169      }
170    
171      /**
172       * Use this method to send a String to the server.
173       */
174      public void send( String s ) {
175        try {
176          this.oos.writeObject(s);
177        } catch (IOException e) {
178          throw new RuntimeException("Client:  failed to send " + s);
179        }
180      }
181    
182      /**
183       * Override default string handling behavior by providing a new
184       * StringHandler.
185       */
186      public void setStringHandler( StringHandler sh ) {
187        this.stringHandler = sh;
188      }
189        
190      /**
191       * This method is passed the String which has been read by the Client
192       * if no other StringHandler has been set.
193       *
194       * Specialize the client by providing an alternate StringHandler.
195       */
196      public void handleString( String s ) {
197        System.out.println("Client:  Got " + s);
198        System.out.flush();
199      }
200    
201      /**
202       *  Closes the socket, stops the thread.  
203       */
204      public void finalize() {
205        this.stopped = true;
206        try {
207          this.sock.close();
208        } catch (IOException e) {}
209      }
210        
211    }
212    
213    
214    /* Comments:
215     *
216     * History:
217     *     $Log: Client.java,v $
218     *     Revision 1.1.1.1  2002/06/05 21:56:32  root
219     *     CS101 comes to Olin finally.
220     *
221     *     Revision 1.8  1998/07/24 17:13:37  tparnell
222     *     Placate new javadoc behavior
223     *
224     *     Revision 1.7  1998/07/22 22:10:32  tparnell
225     *     javadoc fix
226     *
227     *     Revision 1.6  1998/07/22 18:17:49  tparnell
228     *     move from util to net
229     *
230     *     Revision 1.5  1998/07/20 21:35:52  tparnell
231     *     Moved from Data*Stream to Object*Stream.
232     *
233     *     Revision 1.4  1998/07/08 16:11:11  tparnell
234     *     update to JDK1.2: removed refrences to Thread.stop() since it has
235     *     deprecated.
236     *
237     *     Revision 1.3  1998/06/24 21:26:31  tparnell
238     *     code cleanup
239     *
240     *     Revision 1.2  1998/06/03 21:17:46  tparnell
241     *     update from Java 1.0 to 1.1
242     *
243     *     Revision 1.4  1996/11/18 16:41:17  las
244     *     Client, Server, their dependencies (e.g. the Dialogs and their
245     *     invokers) all work.  ClientTester is a bit awkward in that it doesn't
246     *     echo received strings until something is read.  Oh, well.
247     *     Moving them to cs101.util in the next revision.
248     *
249     *     Revision 1.3  1996/11/17 22:28:12  las
250     *     Everything compiles (now).  Client, Server, ClientDialog, ServerDialog,
251     *     StringHandler, and RunServer need to be moved to cs101.util.  But
252     *     first, to test....
253     *
254     *     Revision 1.2  1996/11/17 21:26:52  las
255     *     Client, ClientDialog writen, not yet tested.
256     *
257     *     Revision 1.1  1996/11/17 19:39:30  las
258     *     Intermediate state on the way to an application version.  Some files
259     *     here actually belong in CS101.  Otherwise, the general file structure
260     *     is correct, but the file contents are in some cases grossly out of
261     *     line.
262     *
263     *     Desired structure:
264     *     SharedWhiteboardDemo runs the (client side of the) demo.
265     *     SharedWhiteboard is a helper file that starts things up correctly;
266     *     it's the class definition, though, not the main (which is in
267     *     SharedWhiteboardDemo).
268     *     NetScribbleData is ScribbleData that sets up a client connection.  It
269     *     uses StringHandler and Client.
270     *     StringHandler, ClientDialog, ServerDialog, and maybe Client and Server
271     *     go in the cs101 package.  StringHandler is the interface Client uses.
272     *     ClientDialog and ServerDialog are QueryDialogs specialized for
273     *     obtaining the appropriate information.  Client and Server are pretty
274     *     generic (Server is a broadcaster and Client has send and
275     *     StringHandler.handleString.)
276     *     Fall 96, they write SharedWhiteboard(Demo), NetScribbleData, and
277     *     Client.
278     *
279     *     Revision 1.5  1996/08/04 10:04:30  reuben
280     *     made PORT and SERVER private protected
281     *
282     *     Revision 1.4  1996/08/01 18:26:16  reuben
283     *     More javadoc tweaking (hopefully the final pass)
284     *
285     *     Revision 1.3  1996/08/01 01:56:33  reuben
286     *     Yesturday's changes were tested.
287     *     (I wonder if using cvs and $log$ creates a circular modifcation problem)
288     *
289     *     Revision 1.2  1996/07/30 21:39:25  reuben
290     *     Changed the way the client decides which host and port to connect to:
291     *     Client looks for applet params.  If undefiened or unusable,
292     *     Client uses a default port and connects to the server that the applet
293     *     was downloaded from.  If using appletviewer, default is to connect to
294     *     the machine you are on.
295     *     Note: These changes have not yet been tested.
296     *
297     *     Revision 1.1.1.1  1996/07/18 17:38:24  sit
298     *     Import from /mit/6.096/share/classes after 6.80s session
299     *
300     *     Revision 1.1  1996/07/02 21:47:51  las
301     *     Initial revision
302     *
303     *
304     */
305    
306