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