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