001 /* 002 * Generic Server Application 003 * $Id: Server.java,v 1.1.1.1 2002/06/05 21:56:32 root 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 013 package cs101.net; 014 015 import cs101.awt.ServerDialog; 016 import java.net.*; 017 import java.io.*; 018 import java.util.*; 019 020 /** 021 * Generic Server class: broadcasts whatever messages it receives to 022 * all clients other than the message's originator. Spawns one thread to 023 * listen and multiple others to handle the clients as they connect. 024 * <p> 025 * Takes a single optional argument to specify the port. Otherwise 026 * spawns a UI dialog to get connection information from the user. 027 * <p> 028 * Some hints taken from ORA Servers. 029 * <p> 030 * Copyright 1996 Massachusetts Institute of Technology 031 * 032 * @see cs101.net.RunServer 033 * @see cs101.net.Client 034 * @see cs101.awt.ServerDialog 035 * 036 * @author Todd C. Parnell, tparnell@ai.mit.edu 037 * @author Maciej Stachowiak, maciej@ai.mit.edu 038 * @author Emil Sit, sit@mit.edu 039 * @author Joshua Reuben Brown, reuben@ai.mit.edu 040 * @author Lynn Andrea Stein, las@ai.mit.edu 041 * @version $Id: Server.java,v 1.1.1.1 2002/06/05 21:56:32 root Exp $ 042 * 043 */ 044 public class Server implements Runnable { 045 046 /** the server socket, i.e., the listener */ 047 protected ServerSocket sock; 048 049 /** list of BabySitters to handle each client connection */ 050 protected Vector babySitters; 051 052 /** animating Thread */ 053 protected Thread spirit; 054 055 /** 056 * Creates a server socket. Waits for connections. 057 * No argument version prompts users for port information. 058 */ 059 public Server () { 060 ServerDialog sd = new ServerDialog(); 061 sd.ask(); 062 this.listenOn( sd.getPort() ); 063 } 064 065 /** 066 * Creates a server socket. Waits for connections. 067 * 068 * @param port The integer representing the port number to listen on. 069 */ 070 public Server( int port ) { 071 this.listenOn( port ); 072 } 073 074 /** 075 * Helper method to actually open the ServerSocket and intialize 076 * other state. Also spawns Thread to continue listening. Called 077 * internally. 078 * 079 * @param port The integer representing the port number to listen on. 080 */ 081 protected void listenOn( int port ) { 082 System.out.println("Server: starting up on port " + port ); 083 try { 084 this.sock = new ServerSocket( port ); 085 } catch (IOException e) { 086 throw new RuntimeException("Server: failed to listen on port " 087 + port ); 088 } 089 this.babySitters = new Vector(); 090 this.spirit = new Thread( this ); 091 this.spirit.start(); 092 } 093 094 /** 095 * Wait loop to service the ServerSocket. Called by this server's 096 * Thread. Should not be called externally. 097 * Each time that a connection is recieved, forks a BabySitter to 098 * handle that connection. 099 */ 100 public void run() { 101 try { 102 while ( true ) { 103 System.out.println("Server: listening for a connection"); 104 this.spawnBabySitter( this.sock.accept() ); 105 } 106 } catch (IOException e) { 107 System.out.println( "Server: abrupt failure on accept attempt." ); 108 System.out.println( "Server: no longer accepting connections." ); 109 } 110 } 111 112 /** 113 * Removes a BabySitter for the list of babySitters. 114 * 115 * @param bbst the BabySitter to be remooved from use. 116 */ 117 protected void removeBabySitter(BabySitter bbst) { 118 this.babySitters.removeElement(bbst); 119 bbst.stop(); 120 } 121 122 /** 123 * Creates a BabySitter with the client socket passed and 124 * adds it to the list of BabySitters. 125 * 126 * @param s the client socket that this BabySitter will handle 127 */ 128 protected void spawnBabySitter(Socket s) { 129 BabySitter bbst=new BabySitter(s, this); 130 babySitters.addElement(bbst); 131 } 132 133 /** 134 * Sends the string passed in to all clients accept the one 135 * represented by the BabySitter passed in. 136 * 137 * @param s the string to send 138 * @param bbst the BabySitter that handle the client that we don't want to 139 * send to (the client that the message came from). 140 */ 141 protected void sendToAllExcept(String s, BabySitter bbst) { 142 for(Enumeration e=babySitters.elements();e.hasMoreElements();) { 143 BabySitter current = (BabySitter) e.nextElement(); 144 if (current != bbst) { 145 current.send(s); 146 } 147 } 148 } 149 } 150 151 /* Comments: 152 * 153 * History: 154 * $Log: Server.java,v $ 155 * Revision 1.1.1.1 2002/06/05 21:56:32 root 156 * CS101 comes to Olin finally. 157 * 158 * Revision 1.5 1998/07/24 17:13:45 tparnell 159 * Placate new javadoc behavior 160 * 161 * Revision 1.4 1998/07/22 18:18:07 tparnell 162 * move from util to net 163 * 164 * Revision 1.3 1998/06/24 16:18:24 tparnell 165 * more revisions from summer98 166 * 167 * Revision 1.2 1998/06/03 21:32:08 tparnell 168 * conversion from Java 1.0 to 1.1 169 * 170 * Revision 1.6 1996/11/18 17:10:24 las 171 * All files appear to be working. Some of the files in this directory 172 * belong in cs101.util. These will be moved Real Soon Now. Also, added 173 * ClientMonitor, which watches net traffic but doesn't send. 174 * 175 * Revision 1.5 1996/11/18 16:41:21 las 176 * Client, Server, their dependencies (e.g. the Dialogs and their 177 * invokers) all work. ClientTester is a bit awkward in that it doesn't 178 * echo received strings until something is read. Oh, well. 179 * Moving them to cs101.util in the next revision. 180 * 181 * Revision 1.4 1996/11/17 22:28:16 las 182 * Everything compiles (now). Client, Server, ClientDialog, ServerDialog, 183 * StringHandler, and RunServer need to be moved to cs101.util. But 184 * first, to test.... 185 * 186 * Revision 1.3 1996/11/17 20:43:19 las 187 * Server, RunServer written, not tested. Need to be moved to 188 * cs101.util.... 189 * 190 * Revision 1.2 1996/11/17 20:37:38 las 191 * Server is written, but not yet tested. Should be used with RunServer.java. 192 * 193 * Revision 1.1 1996/11/17 19:39:33 las 194 * Intermediate state on the way to an application version. Some files 195 * here actually belong in CS101. Otherwise, the general file structure 196 * is correct, but the file contents are in some cases grossly out of 197 * line. 198 * 199 * Desired structure: 200 * SharedWhiteboardDemo runs the (client side of the) demo. 201 * SharedWhiteboard is a helper file that starts things up correctly; 202 * it's the class definition, though, not the main (which is in 203 * SharedWhiteboardDemo). 204 * NetScribbleData is ScribbleData that sets up a client connection. It 205 * uses StringHandler and Client. 206 * StringHandler, ClientDialog, ServerDialog, and maybe Client and Server 207 * go in the cs101 package. StringHandler is the interface Client uses. 208 * ClientDialog and ServerDialog are QueryDialogs specialized for 209 * obtaining the appropriate information. Client and Server are pretty 210 * generic (Server is a broadcaster and Client has send and 211 * StringHandler.handleString.) 212 * Fall 96, they write SharedWhiteboard(Demo), NetScribbleData, and 213 * Client. 214 * 215 * Revision 1.5 1996/08/01 18:26:31 reuben 216 * More javadoc tweaking (hopefully the final pass) 217 * 218 * Revision 1.4 1996/08/01 01:56:34 reuben 219 * Yesturday's changes were tested. 220 * (I wonder if using cvs and $log$ creates a circular modifcation problem) 221 * 222 * Revision 1.3 1996/07/30 17:26:00 reuben 223 * Added/corrected javadoc comments. 224 * 225 * Revision 1.2 1996/07/23 21:10:38 reuben 226 * Moved Colorfield and DisplayField to cs101.util package. 227 * Made the necessary changes to PNC. 228 * Compiled and tested all 4 demos. 229 * 230 * Revision 1.1.1.1 1996/07/18 17:38:24 sit 231 * Import from /mit/6.096/share/classes after 6.80s session 232 * 233 * Revision 1.1 1996/07/02 21:47:51 las 234 * Initial revision 235 * 236 */ 237